为什么这两个 float64 有不同的值?

Why do these two float64s have different values?

考虑这两种情况:

fmt.Println(912 * 0.01)
fmt.Println(float64(912) * 0.01)

(Go Playground link)

第二个打印9.120000000000001,其实没问题,I understand why that is happening

但是,为什么第一行打印的是 9.12,而末尾没有 …01? Go 是否将两个无类型常量相乘并在编译时简单地用 9.12 文字替换它们?

输出不同的原因是第一种情况下 912 * 0.01 是任意精度的 2 个无类型常量值的乘积,当值传递给 Println()。 (有关详细信息,请参阅语言规范的 Constant expressions 部分。)

第二种情况float64(912) * 0.01先把912转成float64,再把无类型常量0.01转成float64这两个值float64 相乘,这不是任意精度,不会给出准确的结果。

注:

在第一种情况下,当传递给 Println():

时,结果将被转换为 float64
fmt.Printf("%T %v\n", 912 * 0.01, 912 * 0.01)

输出:

float64 9.12

Test it on Go Playground

根据spec

Constant expressions are always evaluated exactly; intermediate values and the constants themselves may require precision significantly larger than supported by any predeclared type in the language.

开始
912 * 0.01

是一个常量表达式,它被精确计算。因此,写 fmt.Println(912 * 0.01) 与写 fmt.Println(9.12) 具有相同的效果。当您将 912 固定到 float64 时,浮点乘法的另一个操作数也隐式固定到 float64。因此,表达式 float64(912) * 0.01 的行为类似于 float64(912) * float64(0.01)。 0.01 在 float64 中不能完全表示,因此精度在与第一个示例中 fmt.Println() 的参数中出现的表达式 float64(912 * 0.01) 不同的地方丢失,解释了不同的结果.