在下面的简单计算中,c
和d
最终会得到不同的值(它们会被一个比特关闭)。那是为什么?
a := 4000.0
b := 1e-9
c := a / b
d := 4000.0 / 1e-9
答案 0 :(得分:6)
a
被指定为4000.0
的次最佳值,表示为float64
,其为0x40AF400000000000
且与4000.0
完全对应。
b
是1e-9
的下一个最佳值,表示为float64
,0x3E112E0BE826D695
且对应1.00000000000000006228159145778E-9
。你在这里失去了精确度。
所以在计算c
之前你已经有了一点点不精确。然后,当实际计算c
时,你会失去一些更精确的舍入。
在d
的情况下,只有一个“次佳”正在进行中;将编译时计算的4000.0 / 1e-9
的全精度值表示为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)
}
这是由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
正如你所看到的; c
是在运行时根据我描述的两个常量计算的。