2016-11-22 3 views
1

Ich versuche die Gleitkommaarithmetik hinter diesem einfachen Beispiel zu verstehen. Beide Codes sind in der Theorie arithmetisch äquivalent, aber offensichtlich fügt eine Reihe von Additionen mehr Fehler hinzu als eine einfache Multiplikation.Gleitkommaarithmetik: Summierung versus Multiplikation des Fehlers

s=0.0 
for i in range(10): 
    s += 0.1 
print(s) 
print('%.30f' % s) 

0.9999999999999999 
0.999999999999999888977697537484 

aber:

s=0.1 
s *= 10 
print(s) 
print('%.30f' % s) 
1.0 
1.000000000000000000000000000000 

Ich möchte verstehen, was hinter den Kulissen vor sich geht.

Ich verstehe, dass die binäre Darstellung der Dezimalzahl 0,1 nie genau ist, und das kann durch überprüft werden:

print(0.1) 
print('%.30f' % 0.1) 
0.1 
0.100000000000000005551115123126 

So in einer Folge von Additionen, dass Rest hält 5.55e-18 Hinzufügen von bis zu den variablen und sehr schnell wächst es.

Allerdings würde ich bei der Multiplikation erwarten, dass der gleiche Rest auch multipliziert wird und es würde wachsen, aber das passiert nicht. Warum das? Jede Art von Optimierung vor der Konvertierung in Binärdateien?

Antwort

2

Es hat nur damit zu tun, wie Ergebnisse gerundet werden (intern, in binär). converts to 0,1

0.1000000000000000055511151231257827021181583404541015625

die

0.0001100110011001100110011001100110011001100110011001101in binary ist.

Multiply that von 10 (1010 binär) und Sie erhalten

1.000000000000000000000000000000000000000000000000000001 

, dass 55 Bits ist; auf 53 Bits gerundet entspricht es 1,0.

Fügen Sie 0,1 zehnmal hinzu und Sie werden eine Folge von Runden durchlaufen (Ihre Annahme, dass der Fehler "die Variable summiert und sehr schnell wächst") ist falsch - warum würde 0,1 mal zehnmal weniger sein als 1.0 dann?). Wenn drucken Sie den vollständigen Dezimalwerte nach jeder Iteration und Sie sollten

0.1000000000000000055511151231257827021181583404541015625 
0.200000000000000011102230246251565404236316680908203125 
0.3000000000000000444089209850062616169452667236328125 
0.40000000000000002220446049250313080847263336181640625 
0.5 
0.59999999999999997779553950749686919152736663818359375 
0.6999999999999999555910790149937383830547332763671875 
0.79999999999999993338661852249060757458209991455078125 
0.899999999999999911182158029987476766109466552734375 
0.99999999999999988897769753748434595763683319091796875 

Blick auf, was passiert, zwischen 0,5 und 0,6, beispielsweise sehen. Fügen Sie die internen binären Werte für 0,5 und 0,1

0.1 + 0.0001100110011001100110011001100110011001100110011001101

Die Antwort ist

0.1001100110011001100110011001100110011001100110011001101 

, dass 55 Bits ist; gerundet auf 53 Bit ist es

0.10011001100110011001100110011001100110011001100110011 

in dezimal, die

0,59999999999999997779553950749686919152736663818359375

, die weniger als 0,6 ist, obwohl man es hätte erwarten können, größer sein.

+0

Danke für die gründliche Erklärung. Es macht jetzt Sinn. – Raf

+0

Es lohnt sich, hinzuzufügen, dass das Runden auf 53 Bits mit IEEE-754 Fließkommaarithmetik zu tun hat. [https://docs.python.org/3/tutorial/floatingpoint.html#representation-error] – Raf

Verwandte Themen