Heim >Backend-Entwicklung >Golang >Warum tritt ein Go-Programm, das „float32' verwendet, in eine Endlosschleife ein, während ein ähnliches Programm, das „float64' verwendet, beendet wird, wenn beide iterativ 0,2 akkumulieren und 0,3 subtrahieren, bis 1,0 überschritten wird?

Warum tritt ein Go-Programm, das „float32' verwendet, in eine Endlosschleife ein, während ein ähnliches Programm, das „float64' verwendet, beendet wird, wenn beide iterativ 0,2 akkumulieren und 0,3 subtrahieren, bis 1,0 überschritten wird?

Linda Hamilton
Linda HamiltonOriginal
2024-12-07 18:21:15286Durchsuche

Why does a Go program using `float32` enter an infinite loop while a similar program using `float64` terminates, when both accumulate 0.2 and subtract 0.3 iteratively until exceeding 1.0?

Gleitkomma-Präzisionsunterschiede in Go: float32 vs. float64

In Go können Gleitkommawerte entweder als float32 oder float64 dargestellt werden , mit unterschiedlicher Präzision. In einem kürzlich durchgeführten Experiment zeigte ein Programm Gleitkommafehler bei Verwendung der Typen float32 und float64.

Das Programm akkumuliert den Gleitkommawert 0,2 mehrmals und subtrahiert bei jeder Iteration 0,3, bis der Wert 1,0 überschreitet. Bei Verwendung von float64 gibt das Programm nach 54 Iterationen 1,000000e 00 aus, ähnlich dem Verhalten desselben Programms in C (bei Verwendung von double).

Bei Verwendung von float32 im Go-Programm wird jedoch eine Unendlichkeit eingegeben Schleife. Diese Inkonsistenz ergibt sich aus der unterschiedlichen Art und Weise, wie Go und C mit float32-Darstellungen umgehen.

Untersuchung der Gleitkommadarstellungen

Mit den Funktionen math.Float32bits und math.Float64bits haben wir kann beobachten, wie Go Dezimalwerte als IEEE 754-Binärwerte darstellt Werte:

float32(0.1): 00111101110011001100110011001101
float32(0.2): 00111110010011001100110011001101
float32(0.3): 00111110100110011001100110011010
float64(0.1): 0011111110111001100110011001100110011001100110011001100110011010
float64(0.2): 0011111111001001100110011001100110011001100110011001100110011010
float64(0.3): 0011111111010011001100110011001100110011001100110011001100110011

Analyse der Genauigkeit von float32

Die Konvertierung dieser Binärwerte in Dezimalwerte zeigt, dass der Anfangswert von a im Go-Programm mit float32 wie folgt lautet:

0.20000000298023224
+ 0.10000000149011612
- 0.30000001192092896
= -7.4505806e-9

Dieser negative Wert verhindert, dass die Schleife jemals erreicht wird 1.0.

Unterschiede bei der C-Implementierung

In C unterscheidet sich das Verhalten aufgrund von Unterschieden in der Handhabung der Float-Konstanten. Go nähert sich 0,1 mit der nächstgelegenen Binärdarstellung an, während C möglicherweise das letzte Bit abschneidet.

Go:   00111101110011001100110011001101 => 0.10000000149011612
C(?): 00111101110011001100110011001100 => 0.09999999403953552

Daher ermöglicht C eine genauere Darstellung von 0,1, was zu einem anderen Ergebnis für die Gleitkommaschleife führt bei Verwendung von float32.

Das obige ist der detaillierte Inhalt vonWarum tritt ein Go-Programm, das „float32' verwendet, in eine Endlosschleife ein, während ein ähnliches Programm, das „float64' verwendet, beendet wird, wenn beide iterativ 0,2 akkumulieren und 0,3 subtrahieren, bis 1,0 überschritten wird?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn