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

Att*_* O. 9 floating-point floating-accuracy go

考虑这两种情况:

fmt.Println(912 * 0.01)
fmt.Println(float64(912) * 0.01)
Run Code Online (Sandbox Code Playgroud)

(去游乐场链接)

第二个打印9.120000000000001,这实际上很好,我明白为什么会这样.

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

fuz*_*fuz 14

根据规格:

始终精确计算常量表达式; 中间值和常量本身可能要求精度明显大于语言中任何预先声明的类型所支持的精度.

以来

912 * 0.01
Run Code Online (Sandbox Code Playgroud)

是一个常量表达式,它是精确计算的.因此,写作fmt.Println(912 * 0.01)与写作具有相同的效果fmt.Println(9.12).当你固定912float64,浮点乘法的另一个操作数也被隐式固定float64.因此,表达式float64(912) * 0.01表现得像float64(912) * float64(0.01).0.01在a中不能完全表示float64,因此精度在不同的地方丢失,而不是在第一个例子float64(912 * 0.01)的论证中出现的表达式fmt.Println(),解释了不同的结果.


icz*_*cza 6

输出不同的原因是在第一种情况下912 * 0.01是2个无类型常量值的乘法,它具有任意精度,并且只有在float64传递值时才将结果转换为Println().(有关详细信息,请参阅语言规范的常量表达式部分.)

在第二种情况下,float64(912) * 0.01首先912转换为float64,然后将无类型常量0.01转换为float64并且这两个值float64相乘,这不是任意精度,并且不会给出精确结果.

注意:

在第一种情况下,结果将转换为float64传递给Println():

fmt.Printf("%T %v\n", 912 * 0.01, 912 * 0.01)
Run Code Online (Sandbox Code Playgroud)

输出:

float64 9.12
Run Code Online (Sandbox Code Playgroud)

在Go Playground上测试它