Go 中的浮点精度差异:float32 与 float64
在 Go 中,浮点值可以表示为 float32 或 float64 ,具有不同的精度级别。在最近的一次实验中,一个程序在使用 float32 和 float64 类型时演示了浮点错误。
该程序多次累加浮点值 0.2,每次迭代减去 0.3,直到该值超过 1.0。当使用 float64 时,程序在 54 次迭代后输出 1.000000e 00,类似于 C 中同一程序的行为(使用 double 时)。
但是,当在 Go 程序中使用 float32 时,会进入无限环形。这种不一致是由于 Go 和 C 处理 float32 表示的不同方式造成的。
检查浮点表示
使用 math.Float32bits 和 math.Float64bits 函数,我们可以观察 Go 如何将十进制值表示为 IEEE 754 二进制value:
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 精度分析
将这些二进制值转换为十进制可以发现,使用 float32 的 Go 程序中 a 的初始值变为:
0.20000000298023224 + 0.10000000149011612 - 0.30000001192092896 = -7.4505806e-9
这个负值会阻止循环到达1.0.
C 实现差异
在 C 中,由于处理浮点常量的方式不同,行为也有所不同。 Go 用最接近的二进制表示来近似 0.1,而 C 可能会截断最后一位。
Go: 00111101110011001100110011001101 => 0.10000000149011612 C(?): 00111101110011001100110011001100 => 0.09999999403953552
因此,C 允许更准确地表示 0.1,从而导致浮点循环产生不同的结果当使用 float32 时。
以上是为什么使用'float32”的 Go 程序会进入无限循环,而使用'float64”的类似程序会终止,当两者迭代累加 0.2 并减去 0.3 直到超过 1.0 时?的详细内容。更多信息请关注PHP中文网其他相关文章!