2017-02-08 2 views
0

Donc à 10000 on va ajouter la valeur 1/10000 10000times. Logiquement, cela donne 10001. Cependant, en raison d'un maculage, cela ne résulte pas de limitations de stockage. Le résultat est 10000.999999992928. je trouve où le maculage se produit, qui est la deuxième addition:Arithmétique de la machine et Smearing: ajout d'un petit nombre

1: 10000.0001 
2: 10000.000199999999 
3: 10000.000299999998 
4: 10000.000399999997 
etc... 

Cependant, saisir pourquoi le maculage a eu lieu est l'endroit où se trouve la lutte. J'écrit le code pour générer des nombres binaires à virgule flottante pour voir si maculage a eu lieu ici

So 10000 = 10011100010000 or 1.001110001*10**13 while 

0.0001= 0.00000000000001101001 or 

1.1010001101101110001011101011000111000100001100101101*2**(-14) 

then 10000.0001 = 10011100010000.00000000000001101001 

Maintenant, le maculage se produit dans la prochaine addition. Cela a-t-il un rapport avec la taille de la mantisse? Pourquoi cela se produit-il seulement dans cette étape? Juste intéressé de savoir. Je vais d'abord ajouter tout le 1/10000 puis l'ajouter au 10000 pour éviter les smaings.

+0

Vous feriez peut-être mieux de trouver un bon guide général pour les représentations en virgule flottante. Je recommande [* Ce que tout scientifique informatique devrait savoir à propos de l'arithmétique en virgule flottante * par David Goldberg] (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html), ou, pour un trajet plus doux, le site web de [* Floating-Point Guide * (http://floating-point-gui.de/). –

Répondre

0

Le petit « barbouiller » erreur pour une seule addition peut être calculée exactement comme

a=10000; b=0.0001 
err = ((a+b)-a)-b 
print "err=",err 

>>> err= -7.07223084891e-13 

L'erreur d'arrondi d'un ajout est de taille (abs(a)+abs(b))*mu/2 ou autour 1e4 * 1e-16 = 1e-12, ce qui correspond bien le résultat calculé. En général, vous devez également tester l'expression ((a+b)-b)-a, mais l'une d'elles est toujours zéro, ici la dernière. En effet, cette erreur unique accumulée sur l'ensemble des étapes donne déjà le résultat observé, les erreurs secondaires liées à l'augmentation lente de la somme au premier terme dans chaque addition ayant un impact beaucoup plus faible.

print err*10000 
>>> -7.072230848908026e-09 
print 10001+err*10000 
>>> 10000.999999992928 
0

Le principal problème est que 1/10000-à-dire 0.0001 ne peut pas être encodées exactement comme une valeur flottante de la machine (voir la norme IEEE 754), puisque 10000 est pas une puissance de 2. Aussi 1/10 = 0.1 ne peut pas être codé comme flotteur de la machine, de sorte que vous ferez l'expérience phanomena comme 0.1 + 0.1 + 0.1 > 0.3.

Lors du calcul avec double précision (64 bits) ce qui suit est:

1.0001 - 1 < 0.0001 
10000.0001 + 9999*0.0001 == 10001 

Je suppose que vous calculez avec une précision unique (32 bits)?