首頁 >後端開發 >Golang >Go 與 C:為什麼浮點精準度會在 Go 的 Float32 中導致無限循環,而在 C 的 Double 中卻不會?

Go 與 C:為什麼浮點精準度會在 Go 的 Float32 中導致無限循環,而在 C 的 Double 中卻不會?

Barbara Streisand
Barbara Streisand原創
2024-12-09 17:01:10912瀏覽

Go vs. C: Why Does Floating-Point Precision Cause an Infinite Loop in Go's Float32 but Not in C's Double?

Go Lang 浮點精度:Float32 與 Float64

為了說明 Go中浮點運算的複雜性,請考慮以下程序,該程序演示了精度的影響:

func main() {
    a := float64(0.2)
    a += 0.1
    a -= 0.3
    var i int
    for i = 0; a < 1.0; i++ {
        a += a
    }
    fmt.Printf("After %d iterations, a = %e\n", i, a)
}

該程序表現出預期的行為C 在使用double 類型時,打印:

After 54 iterations, a = 1.000000e+00

但是在Go 中使用float32 時,程式會進入死循環。修改C 程式以使用float 而不是double 會產生不同的結果:

After 27 iterations, a = 1.600000e+00

要理解這種差異,請使用math.Float32bits 和math.Float64bits 深入研究底層二進位表示:

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

將這些二進位值轉換為十進位顯示,對於float32,a 的初始值變成:

0.20000000298023224
+ 0.10000000149011612
- 0.30000001192092896
= -7.4505806e-9

這個負值永遠不可能等於 1,導致觀察到的無限循環。

相反,C 的行為源自於舍入策略的差異。 Go 會捨入最後一位,而 C 可能會將其裁切掉。因此,Go 將0.1 表示為最接近它的值:

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

總之,Go 和C 都不能精確地表示浮點數中的0.1,但Go 使用最接近的近似值,而C 可能會根據不同情況進行不同的處理。實施。

以上是Go 與 C:為什麼浮點精準度會在 Go 的 Float32 中導致無限循環,而在 C 的 Double 中卻不會?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn