当前位置: 首页 > 知识库问答 >
问题:

Golang浮点精度浮点32 vs浮点64

萧浩漫
2023-03-14

我编写了一个程序来演示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)
}

它打印:

After 54 iterations, a = 1.000000e+00

这与用C编写的相同程序的行为相匹配(使用双代码类型)

但是,如果改用float32,程序就会陷入无限循环!如果将C程序修改为使用float而不是double,它将打印

After 27 iterations, a = 1.600000e+00

为什么在使用float32时,Go程序的输出与C程序的输出不一样?

共有2个答案

傅朝
2023-03-14

同意阿尼萨斯,围棋是在做正确的事。关于C,我不相信他的猜测。

C标准没有规定,但大多数libc实现都会将十进制表示转换为最接近的浮点(至少符合IEEE-754 2008或ISO 10967),因此我认为这不是最可能的解释。

C程序行为可能不同的原因有很多。。。特别是,某些中间计算可能会执行过高精度(双精度或长双精度)。

我能想到的最可能的事情是,如果你在C中写了0.1而不是0.1f。
在这种情况下,你可能会在初始化
中导致过高的精度(你和浮点数相加为双0.1=

如果我模仿这些操作

float32(float32(float32(0.2) + float64(0.1)) - float64(0.3))

然后我发现1.1920929e-8f附近有东西

经过27次迭代后,其总和为1.6f

陈项禹
2023-03-14

使用数学。Float32bit数学。Float64bit,您可以看到Go如何将不同的十进制值表示为IEEE 754二进制值:

游乐场:https://play.html" target="_blank">golang.org/p/ZqzdCZLfvC

结果:

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和C都不能在浮点中精确表示0.1,但Go使用最接近0.1的值:

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

编辑:

我发布了一个关于C如何处理浮点常量的问题,从答案来看,似乎任何C标准的实现都可以这样做。您尝试过的实现只是做得与Go不同。

 类似资料:
  • 问题内容: 我编写了一个程序来演示Go中的浮点错误: 它打印: 这与用C编写的同一程序的行为匹配(使用类型) 但是,如果使用,则该程序将陷入无限循环!如果您将C程序修改为使用a 而不是a ,则会输出 使用时,为什么Go程序没有与C程序相同的输出? 问题答案: 同意ANisus,go在做正确的事。关于C,我不相信他的猜测。 C标准没有规定,但是libc的大多数实现会将十进制表示形式转换为最接近的浮点

  • 问题内容: $a = ‘35’; $b = ‘-34.99’; echo ($a + $b); 结果为0.009999999999998 这是怎么回事?我想知道为什么我的程序不断报告奇怪的结果。 为什么PHP不返回预期的0.01? 问题答案: 因为浮点运算!=实数运算。对于一些浮子和,由不精确性引起的差异的说明是。这适用于使用浮点数的任何语言。 由于浮点数是具有有限精度的二进制数,因此存在有限数量

  • 本文向大家介绍Fortran 浮点数精度,包括了Fortran 浮点数精度的使用技巧和注意事项,需要的朋友参考一下 示例 类型的浮点数real不能有任何实数值。它们可以表示实数,最多可以包含一定数量的十进制数字。 FORTRAN 77保证了两种浮点类型,而最新的标准则至少保证了两种实数类型。实变量可以声明为 x这是默认类型的实数,并且y是比更大的十进制精度的实数x。在Fortran 2008中,十

  • 问题内容: 我正在读取一个带有浮点数的文本文件,这些数字都带有1或2个小数点。我正在使用将线转换为浮点数,并在失败的情况下引发。我将所有花车存储在列表中。打印时,我想将其打印为2个小数位的浮点数。 假设我有一个文本文件,其编号为-3,65、9,17、1。我阅读了每个文件,然后将它们转换为float并将它们附加到列表中。现在在Python 2中,调用return 。但是在Python 3中,-3.6

  • 运行以下代码时,我希望收到这样的输出: 但结果如下: 欢迎任何能指导我正确使用浮点比较和正确使用setprecision的建议。