est ici l'essence de votre confusion:
En raison de virgule flottante représentation précision, cela pourrait être quelque chose comme 122.99999999999999999999 ou 123.000000000000000000001.
Ceci est faux. Il sera toujours exactement 123 sur un système conforme à la norme IEEE-754, qui est presque tous les systèmes dans ces temps modernes. L'arithmétique à virgule flottante n'a pas «d'erreur aléatoire» ou de «bruit». Il a des arrondis précis et déterministes, et de nombreux calculs simples (comme celui-ci) n'entraînent aucun arrondi.
123
est exactement représentable en virgule flottante, et ainsi est 123*123
(donc tous sont entiers de taille modeste). Donc, aucune erreur d'arrondi ne se produit lorsque vous convertissez 123*123
en un type à virgule flottante. Le résultat est exactement15129
.
La racine carrée est une opération correctement arrondie, conformément à 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 exactement15129
, qui est exactement 123
, c'est exactement le résultat que vous obtenez de la fonction de la racine carrée. Aucun arrondi ou approximation ne se produit.
Maintenant, pour quelle taille d'un nombre entier cela sera-t-il vrai? La double précision peut représenter exactement tous les entiers jusqu'à 2^53. Donc, tant 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 tout i
plus petit que 94906265
, nous savons que le calcul sera exact.
Mais vous avez essayé i
plus grand que ça! Que ce passe-t-il?
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). Puisque les conversions d'entier en double (ou de multiplication en double) sont également correctement arrondies opérations, i*i
sera la valeur représentable la plus proche du carré exact de i
. Dans ce cas, puisque i*i
a une largeur de 54 bits, l'arrondi se produira dans le bit le plus bas. Ainsi, nous savons que:
i*i as a double = the exact value of i*i + rounding
où est soit -1,0, or 1
. Si l'arrondi est nul, alors le carré est exact, donc la racine carrée est exacte, donc nous savons déjà que vous obtenez la bonne réponse. Ignorons ce cas.
Donc maintenant nous regardons la racine carrée de i*i +/- 1
. En utilisant une valeur de cette racine carrée est l'expansion de Taylor, l'infiniment précis (unrounded):
i * (1 +/- 1/(2i^2) + O(1/i^4))
Maintenant, c'est un peu Checklist pour voir si vous ne l'avez pas fait une analyse d'erreur de virgule flottante avant, mais si vous utiliser le fait que i^2 > 2^53
, vous pouvez voir que:
1/(2i^2) + O(1/i^4)
terme est inférieur à 2^-54, ce qui signifie que (depuis la racine carrée est arrondie correctement, et donc son erreur d'arrondi doit être inférieur à 2^54), le résultat arrondi de la fonction sqrt est exactement i
.
Il s'avère que (avec une analyse similaire), pour tout nombre à virgule flottante exactement représentable x, sqrt (x * x) est exactement x (en supposant que le calcul intermédiaire de x*x
ne dépasse pas ou ne dépasse pas), La seule façon de contourner ce type de calcul est donc la représentation de x
lui-même, c'est pourquoi vous le voyez à partir de 2^53 + 1
(le plus petit nombre non représentable).
Vous pouvez changer 'i = 0; 100000000.times {met je; i + = 1} 'à' 100000000.times {| i | met i} ' –
à droite, merci. c'est un peu plus simple maintenant – martinus