首页 >后端开发 >Golang >为什么使用'float32”的 Go 程序会进入无限循环,而使用'float64”的类似程序会终止,当两者迭代累加 0.2 并减去 0.3 直到超过 1.0 时?

为什么使用'float32”的 Go 程序会进入无限循环,而使用'float64”的类似程序会终止,当两者迭代累加 0.2 并减去 0.3 直到超过 1.0 时?

Linda Hamilton
Linda Hamilton原创
2024-12-07 18:21:15286浏览

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?

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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn