8
votes

Pourquoi est-ce que math.sqrt (i * i) .floor == i?

Je me demande si cela est vrai: lorsque je prends la racine carrée d'un entier carré, comme dans

100_000_000.times do |i|
  puts i if Math.sqrt(i*i).floor != i
end


2 commentaires

Vous pouvez changer i = 0; 100000000.time {met i; i + = 1} à 100000000.time {| i | met i}


Droite, merci. c'est un peu plus simple maintenant


4 Réponses :


15
votes

pour "petit" entiers, il existe généralement une représentation exacte du point flottant.


4 commentaires

Oui. La représentation des points flottants est exacte pour tous les entiers ayant moins de bits significatifs que la mantissie de la représentation du point flottant: 23 bits pour une précision unique, 52 pour le double si nous parlons de IEEE 754. Grâce à un meneur implicite 1 dans la Mantissa, C'est en fait 24 et 53.


+1: En règle générale, pensez aux flotteurs comme ayant 48 bits de précision utiles. (Les tailles réelles varient, mais vous pouvez travailler avec 48 en règle générale). Afin d'accéder à un endroit où le dernier bit importe réellement, vous devez travailler avec un produit d'INT qui a une taille d'au moins 48 bits.


Merci, tu as raison. Il commence à arrêter de travailler au 9007199254740993, ce qui est 2 ^ 53 + 1


Woo Hoo, merci de vérifier! S.Lott m'avait inquiet pendant un moment! :)



7
votes

Il n'est pas trop difficile de trouver des cas où cela se décompose comme prévu:

Math.sqrt(94949493295293425**2).floor
# => 94949493295293424
Math.sqrt(94949493295293426**2).floor
# => 94949493295293424
Math.sqrt(94949493295293427**2).floor
# => 94949493295293424


1 commentaires

Et math.sqrt (94949493295293423 ** 2) .floor ==> 94949493295293424 , aussi.



3
votes

Le flotteur de Ruby est un numéro de point flottant à double précision, ce qui signifie qu'il peut représenter avec précision des nombres avec (règle de point de pouce) environ 16 chiffres décimaux significatifs. Pour les nombres de points flottants réguliers de la précision unique, il s'agit de 7 chiffres significatifs.

Vous pouvez trouver plus d'informations ici:

Quel est ce que chaque informatique doit savoir sur l'arithmétique de points flottants: http://docs.sun.com/source/819-3693/ncg_goldberg. HTML


0 commentaires

23
votes

Voici l'essence de votre confusion:

en raison de la représentation des points flottants précision, cela pourrait être quelque chose comme 122.9999999999999999999999 ou 123.00000000000000000000001.

Ceci est faux. Ce sera toujours exactement 123 sur un système compatible IEEE-754, qui constitue presque tous les systèmes de ces temps modernes. L'arithmétique à virgule flottante n'a pas de "erreur aléatoire" ou de "bruit". Il a un arrondi précis, déterministe et de nombreux calculs simples (comme celui-ci) n'entraînent aucun arrondi.

123 est exactement représentable dans le point flottant, et c'est ainsi que 123 * 123 (Ainsi sont tous les entiers de taille modeste Donc, aucune erreur d'arrondi ne se produit lorsque vous convertissez 123 * 123 sur un type à virgule flottante. Le résultat est exactement 15129 .

la racine carrée est une opération correctement arrondie par la norme IEEE-754. Cela signifie que s'il y a une réponse exacte, la fonction racine carrée est nécessaire pour la produire. Puisque vous prenez la racine carrée de exactement 15129 , qui est exactement 123 , c'est exactement < / em> le résultat obtenu de la fonction racine carrée. Aucun arrondi ou approximation ne se produit.

Maintenant, pour la taille d'un entier cela sera vrai?

double précision peut représenter tous les entiers jusqu'à 2 ^ 53. Ainsi, aussi longtemps que i * i est inférieur à 2 ^ 53, aucun arrondi ne se produira dans votre calcul, et le résultat sera exact pour cette raison. Cela signifie que pour tous i plus petit que 94906265 , nous savons que le calcul sera exact.

mais vous avez essayé i Plus grand que ça! Qu'est-ce qui se passe?

pour le plus grand i que vous avez essayé, i * i est juste à peine plus grand que 2 ^ 53 ( 1.1102 .. . * 2 ^ 53 , en fait). Parce que les conversions d'entier à double (ou multiplication en double) sont également correctement arrondies les opérations, i * i sera la valeur représentable la plus proche du carré exact de i . Dans ce cas, étant donné que i * i est de 54 bits de large, l'arrondi se produira au plus bas bit. Ainsi, nous savons que: xxx

arrondi est soit -1,0, ou 1 . Si l'arrondi est zéro, le carré est exact, de sorte que la racine carrée est exacte, donc nous savons déjà que vous obtenez la bonne réponse. Ignorons ce cas.

Alors maintenant, nous regardons la racine carrée de i * i * i +/- 1 . Utilisation d'une expansion de la série Taylor, la valeur infiniment précise (non heurée) de cette racine carrée est la suivante: xxx

C'est un peu fidèle à voir si vous n'avez fait aucun flottant Analyse des erreurs de point Auparavant, mais si vous utilisez le fait que i ^ 2> 2 ^ 53 , vous pouvez voir que le: xxx

terme est plus petit que 2 ^ -54, ce qui signifie que (car la racine carrée est correctement arrondie et que son erreur arrondi doit être inférieure à 2 ^ 54), le résultat arrondi de la fonction SQRT est exactement i .

Il s'avère que (avec une analyse similaire), pour tout numéro de point flottant représentable X, sqrt (x * x) est exactement x (en supposant que le calcul intermédiaire de x * x ne pas trop ou sous le flux de flux), de sorte que la seule façon de rencontrer l'arrondi pour ce type de calcul est dans la représentation de x lui-même, c'est pourquoi Vous le voyez à partir de 2 ^ 53 + 1 (le plus petit entier non représentable).


1 commentaires

Wow. Traitement très complet (et précis), +1.