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) }
これdouble 型を使用すると、プログラムは C で予期される動作を示し、
After 54 iterations, a = 1.000000e+00
を表示します。ただし、Go で float32 を使用すると、プログラムは無限ループに入ります。 C プログラムを変更して double の代わりに float を使用すると、異なる結果が得られます:
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
これらのバイナリ値を 10 進数に変換すると、float32 の場合、
0.20000000298023224 + 0.10000000149011612 - 0.30000001192092896 = -7.4505806e-9
この負の値は合計が 1 になることはなく、観察された無限ループにつながります。
対照的に、C の動作は丸め戦略の違いに起因します。 Go は最後のビットを丸めますが、C はおそらくそれをトリミングします。その結果、Go は 0.1 に最も近い値として 0.1 を表します。
Go: 00111101110011001100110011001101 => 0.10000000149011612 C(?): 00111101110011001100110011001100 => 0.09999999403953552
要約すると、Go と C はどちらも float で 0.1 を正確に表すことはできませんが、Go は最も近い近似を使用するのに対し、C は状況に応じて異なる方法で処理する可能性があります。実装。
以上がGo vs. C: 浮動小数点精度によって Go の Float32 では無限ループが発生するのに、C の Double では発生しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。