为什么浮点文字和变量在Go中给出不同的结果?

jas*_*x43 3 go

在下面的简单的计算,cd结束了不同的值(它们是关闭的单个位).这是为什么?

a := 4000.0
b := 1e-9
c := a / b
d := 4000.0 / 1e-9
Run Code Online (Sandbox Code Playgroud)

thw*_*hwd 6

a被指定为下一个最佳值,4000.0表示为a float64,它0x40AF400000000000恰好对应4000.0.

b是下一个最佳值1e-9,表示为a float64,0x3E112E0BE826D695对应于1.00000000000000006228159145778E-9.你在这里失去了精确度

所以在计算之前c你已经有了一点点不精确.然后,当c实际计算时,你会失去一些更精确的舍入.

在这种情况下d,只有一个"次佳"正在进行; 当表示编译时计算的全精度值为4000.0 / 1e-9a时float64.

除了变量之外:在C(并且可能是C++)中,默认是假设变量是非易失性的,即不共享,因此优化通常深入地遵循常量表达式,用计算值替换所有变量.Go不对变量的范围做出任何假设,因此无法保证替换常量表达式.这可能会在将来发生变化,但是今天在该部门中并没有做太多的事情,因此很可能c实际上是在运行时计算的,而不是在编译时计算出来的,因为有人习惯于C.


编辑:我已经采取了@topskip提供的程序:

package main

import "fmt"

func main() {
    a := 4000.0
    b := 1e-9
    c := a / b
    d := 4000.0 / 1e-9
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
}
Run Code Online (Sandbox Code Playgroud)

这是由以下组件生成的程序集的一部分go tool 6g -S:

0x0021 00033 (meh.go:6) MOVSD   $f64.40af400000000000+0(SB),X2
0x002a 00042 (meh.go:7) MOVSD   $f64.3e112e0be826d695+0(SB),X3
0x0033 00051 (meh.go:8) MOVAPD  X2,X0
0x0037 00055 (meh.go:8) MOVSD   X3,"".b+64(SP)
0x003d 00061 (meh.go:8) DIVSD   X3,X0
Run Code Online (Sandbox Code Playgroud)

如你看到的; c在运行时根据我描述的两个常量计算.