[PYTHON] Warum ist die Gleitkommazahl von 0,1 größer als 0,1, aber wenn sie zehnmal addiert wird, ist sie kleiner als 1,0 [Teil 2]

Teil 1

Dies ist eine Fortsetzung dieses Artikels.

Warum ist die Gleitkommazahl von 0,1 größer als 0,1, aber kleiner als 1,0, wenn sie zehnmal hinzugefügt wird [Teil 1]

(Kopie aus dem ersten Teil) Wenn 0.1 durch eine Gleitkommazahl dargestellt wird

Das Vorzeichen, der Exponent und die falsche Zahl, wenn "0,1" als Gleitkommazahl ausgedrückt wird, sind wie folgt.

Code= 0
Index= 01111111011
Mantisse= 1001100110011001100110011001100110011001100110011010

Der Exponent ist "1019" in Dezimalzahl. Dem Gleitkomma-Exponenten wird "1023" hinzugefügt. Wenn Sie dies subtrahieren, erhalten Sie "-4".

(Kopie aus dem ersten Teil) Wie viel zum Ergebnis hinzugefügt wird, wenn 0,1 hinzugefügt wird

Die folgende Tabelle zeigt die Berechnungsergebnisse, wenn "0,1" zu den ungeraden Zeilen ohne den Header hinzugefügt wird, und die Unterschiede zwischen den geraden Zeilen.

Erwarteter Wert Berechnungsergebnis / Differenz
0.1 0.1000000000000000055511151231257827021181583404541015625
0.1000000000000000055511151231257827021181583404541015625
0.2 0.200000000000000011102230246251565404236316680908203125
0.100000000000000033306690738754696212708950042724609375
0.3 0.3000000000000000444089209850062616169452667236328125
0.09999999999999997779553950749686919152736663818359375
0.4 0.40000000000000002220446049250313080847263336181640625
0.09999999999999997779553950749686919152736663818359375
0.5 0.5
0.09999999999999997779553950749686919152736663818359375
0.6 0.59999999999999997779553950749686919152736663818359375
0.09999999999999997779553950749686919152736663818359375
0.7 0.6999999999999999555910790149937383830547332763671875
0.09999999999999997779553950749686919152736663818359375
0.8 0.79999999999999993338661852249060757458209991455078125
0.09999999999999997779553950749686919152736663818359375
0.9 0.899999999999999911182158029987476766109466552734375
0.09999999999999997779553950749686919152736663818359375
1.0 0.99999999999999988897769753748434595763683319091796875

(Kopie aus dem ersten Teil) Verfahren zum Hinzufügen von Gleitkommazahlen

Das Hinzufügen positiver Gleitkommazahlen erfolgt nach dem folgenden Verfahren.

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. ③ Fügen Sie die falschen Nummern hinzu ④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. ⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung).

(Kopie aus dem ersten Teil) Schutzträger und Klebeband

Schutzziffern sind der Bereich, in dem die überlaufenden Ziffern gespeichert werden. Das Sticky-Bit ist ein boolescher Wert, der angibt, ob die Zahl unter der Schutzziffer eine Zahl größer oder gleich 1 enthält.

Im ersten Teil wurde erwähnt, dass eine Schutzziffer zum Hinzufügen positiver Zahlen ausreicht, beim Erweitern auf negative Zahlen jedoch zwei Ziffern erforderlich sind. Im Folgenden werden zwei Schutzziffern und ein klebriges Bit verwendet. Die zwei Ziffern (2 Bits) der Schutzziffer werden von oben als Schutzbit und Rundbit bezeichnet.

Berechnungsprozess, wenn 0,1 10-mal hinzugefügt wird

Überprüfen Sie den Berechnungsprozess, wenn Sie Schritt für Schritt "0.1" hinzufügen.

Diesmal verwendeter Ausdruck

Dieses Mal werde ich anhand der folgenden Abbildung erklären.

f_legend.png

Nummer Spaltenname Erläuterung
Ungefähr Es beschreibt grob, welche Art von Berechnung durchgeführt wird.
Index(Dezimalzahl) 浮動小数点数で表されたIndexを、10進数に変換し、1023を引いたものです。
Bewegen Sie sich nach oben Infolge der Addition können die Ziffern hochgetragen werden, so dass viel Fläche gesichert ist.
Ganzzahliger Teil 浮動小数点形式ではGanzzahliger Teilは常に1ist.
0 bis 52 Es ist eine falsche Nummer. Da es schwierig ist zu sehen, ob alle 52 Ziffern angezeigt werden, werden nur die oberen 8 Ziffern und die unteren 8 Ziffern angezeigt.
Wache rund klebrig Der oben beschriebene Schutzträger und das klebrige Bit.

0,1 + 0,1 Berechnungsprozess

Überprüfen Sie den Berechnungsprozess von "0,1 + 0,1". f0_1_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Da die Indizes gleich sind, wird nichts unternommen.

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis des Hinzufügens f0_1_2.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Da es einen Übertrag gibt, addiere "1" zum Exponenten und dividiere die falsche Zahl durch "2". Da es sich um eine Binärzahl handelt, wird durch Teilen durch 2 eine Ziffer nach rechts verschoben (Bitverschiebung). f0_1_3.png

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Das einzige überlaufende Bit ist "0", also kürzen Sie es. f0_1_4.png

Über,

Index= -3 (Dezimalzahl)
Mantisse= 1001100110011001100110011001100110011001100110011010 (Binärzahl)

Wurde erhalten. Wenn Sie dies in eine Dezimalzahl umwandeln,

0.200000000000000011102230246251565404236316680908203125

ist.

Berechnungsprozess von 0,2 (kumulative Summe) + 0,1

Addiere 0.1 zu dem oben erhaltenen Wert. f0_2_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Der Exponent von "0,2" ist "1" größer, also addieren Sie "1" zum Exponenten von "0,1" und verschieben Sie die falsche Zahl um "1" nach rechts. f0_2_2.png

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis der Addition. f0_2_3.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Da es einen Übertrag gibt, addiere "1" zum Exponenten und verschiebe die falsche Zahl nach rechts "1". f0_2_4.png

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Die überlaufende Ziffer ist "10", was genau der Hälfte entspricht. Runden Sie sie also in gleichmäßiger Richtung ab. Dieses Mal ist das niedrigstwertige Bit der falschen Zahl "1". Runden Sie es also auf. f0_2_5.png

Über,

Index= -2 (Dezimalzahl)
Mantisse= 11001100110011001100110011001100110011001100110100 (Binärzahl)

Wurde erhalten. Wenn Sie dies in eine Dezimalzahl umwandeln,

0.3000000000000000444089209850062616169452667236328125

ist.

In "0,2 (kumulative Summe) + 0,1" ist "0,1" in Gleitkommazahlen ursprünglich größer als "0,1", und das hinzugefügte Ergebnis wird weiter aufgerundet, also "Drucken" Sie werden Ergebnisse sehen, die nicht Ihren Erwartungen entsprechen.

print(0.1 + 0.1 + 0.1)
# => 0.30000000000000004

Berechnungsprozess von 0,3 (kumulative Summe) + 0,1

Addiere 0.1 zu dem oben erhaltenen Wert. f0_3_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Da der Exponent von "0,3" "2" größer ist, addieren Sie "2" zum Exponenten von "0,1" und verschieben Sie die falsche Zahl um "2" nach rechts. f0_3_2.png

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis der Addition. f0_3_3.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Kein Tragen, also nichts tun

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Die überlaufende Ziffer ist "10", was genau der Hälfte entspricht. Runden Sie sie also in gleichmäßiger Richtung ab. Dieses Mal ist das niedrigstwertige Bit der falschen Nummer 0, daher wird es abgeschnitten. f0_3_4.png

Über,

Index= -2 (Dezimalzahl)
Mantisse= 1001100110011001100110011001100110011001100110011010 (Binärzahl)

Wurde erhalten. Wenn Sie dies in eine Dezimalzahl umwandeln,

0.40000000000000002220446049250313080847263336181640625

ist.

Berechnungsprozess von 0,4 (kumulative Summe) + 0,1

Addiere "0.1" zu dem oben erhaltenen Wert. f0_4_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Da der Exponent von "0,4" "2" größer ist, addieren Sie "2" zum Exponenten von "0,1" und verschieben Sie die falsche Zahl um "2" nach rechts. f0_4_2.png

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis der Addition. Alle Werte im formalen Teil sind jetzt "0". f0_4_3.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Da es einen Übertrag gibt, addiere "1" zum Exponenten und verschiebe die falsche Zahl um "1" nach rechts. f0_4_4.png

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Die überlaufende Ziffer ist "010", daher wird sie abgeschnitten. f0_4_5.png

Über,

Index= -1 (Dezimalzahl)
Mantisse= 0000000000000000000000000000000000000000000000000000 (Binärzahl)

Wurde erhalten. Konvertieren Sie dies in eine Dezimalzahl,

0.5

ist. Es war ein Zufall, dass es perfekt wurde.

Berechnungsprozess von 0,5 (kumulative Summe) + 0,1

Addiere "0.1" zu dem oben erhaltenen Wert. f0_5_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Da der Exponent von "0,5" "3" größer ist, addieren Sie "3" zum Exponenten von "0,1" und verschieben Sie die falsche Zahl um "3" nach rechts. f0_5_2.png

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis der Addition. f0_5_3.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Kein Tragen, also nichts tun

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Die überlaufende Ziffer ist "010", daher wird sie abgeschnitten. f0_5_4.png

Über,

Index= -1 (Dezimalzahl)
Mantisse= 11001100110011001100110011001100110011001100110011 (Binärzahl)

Wurde erhalten. Konvertieren Sie dies in eine Dezimalzahl,

0.59999999999999997779553950749686919152736663818359375

ist.

Berechnungsprozess von 0,6 (kumulative Summe) + 0,1, 0,7 (kumulative Summe) + 0,1, 0,8 (kumulative Summe) + 0,1

Da "0,6" bis "0,8" fast gleich "0,5 (kumulative Summe) + 0,1" sind, werden sie weggelassen. In diesem Bereich wurden aufgrund von Wertkürzungen Werte unter "1" hinzugefügt.

Berechnungsprozess von 0,9 (kumulative Summe) + 0,1

Dies entspricht fast 0,5 (kumulative Summe) + 0,1, aber lassen Sie uns sehen, wie das Ergebnis aussieht. f0_9_1.png

① Passen Sie den kleineren Index an den größeren Index an (2) Passen Sie die Einstellung an, indem Sie die falsche Anzahl verringern, wenn der Exponent erhöht wird. Da der Exponent von "0,9" größer als "3" ist, addieren Sie "3" zum Exponenten von "0,1" und verschieben Sie die falsche Zahl um "3" nach rechts. f0_9_2.png

③ Fügen Sie die falschen Nummern hinzu Es ist das Ergebnis der Addition. f0_9_3.png

④ Wenn ein Übertrag auftritt, addieren Sie 1 zum Exponenten und reduzieren Sie die falsche Zahl entsprechend. Kein Tragen, also nichts tun

⑤ Runden Sie die überlaufenden Ziffern der falschen Zahl (gerade Rundung). Die überlaufende Ziffer ist "010", daher wird sie abgeschnitten. f0_9_4.png

Über,

Index= -1 (Dezimalzahl)
Mantisse= 1111111111111111111111111111111111111111111111111111 (Binärzahl)

Wurde erhalten. Konvertieren Sie dies in eine Dezimalzahl,

0.99999999999999988897769753748434595763683319091796875

ist.

Bis zu diesem Punkt haben wir den Vorgang bestätigt, wenn "0,1" 10 Mal hinzugefügt wird.

Zusammenfassung

Die Antwort lautet: Wenn "0.1" eine Gleitkommazahl ist, ist sie etwas größer als "0.1", aber wenn sie zehnmal addiert wird, ist sie kleiner als "1.0". Dies lag daran, dass wir beim Hinzufügen von zwei Gleitkommazahlen Zahlen abgerundet haben, die nicht in die falsche Zahl passen.

Referenzmaterial

Verwendete Werkzeuge usw.

Recommended Posts

Warum ist die Gleitkommazahl von 0,1 größer als 0,1, aber wenn sie zehnmal addiert wird, ist sie kleiner als 1,0 [Teil 1]
Warum ist die Gleitkommazahl von 0,1 größer als 0,1, aber wenn sie zehnmal addiert wird, ist sie kleiner als 1,0 [Teil 2]
Warum wird 0,1 beim Drucken als 0,1 angezeigt, obwohl 0,1 nicht durch eine Gleitkommazahl genau dargestellt werden kann?
Überprüfen Sie die speicherinterne Byte-Zeichenfolge der Gleitkommazahl in Python
Es scheint, dass die Version von Pyflakes nicht die neueste ist, wenn flake8 installiert ist
Tiefes Lernen! Die Geschichte der Daten selbst, die gelesen werden, wenn sie nach der handschriftlichen Nummernerkennung nicht folgen