只要使用浮点,就无法在内存中精确表示0.1,因此我们知道该值通常为0.10000000000000004。
但是当使用去添加0.1和0.2。我得到0.3。
fmt.Println(0.1 + 0.2) // Output : 0.3
为什么0.3而不是0.30000000000000004出现?
这是因为在打印时(例如与fmt包装一起),打印功能已经四舍五入到一定数量的小数位。
fmt
请参阅以下示例:
const ca, cb = 0.1, 0.2 fmt.Println(ca + cb) fmt.Printf("%.20f\n", ca+cb) var a, b float64 = 0.1, 0.2 fmt.Println(a + b) fmt.Printf("%.20f\n", a+b)
输出(在Go Playground上尝试):
0.3 0.29999999999999998890 0.30000000000000004 0.30000000000000004441
首先,我们使用常量,因为这与使用type的(非常量)值不同float64。 数字常数表示任意精度的精确值,并且不会溢出。
float64
但是在打印的结果时ca+cb,必须将常量值转换为非常量类型的值才能传递给fmt.Println()。该值将是类型float64,不能完全表示0.3。但是fmt.Println()会将其舍入为〜16个小数位,即0.3。但是,当我们明确声明要以20位数字显示时,我们会发现它不准确。请注意,只会0.3将转换为float64,因为常量算术0.1+0.2将由编译器评估(在编译时)。
ca+cb
fmt.Println()
0.3
0.1+0.2
接下来,我们从type变量开始,float64毫不奇怪,输出不是0.3完全正确,但是这次即使使用默认舍入,我们得到的结果也不同于0.3。这样做的原因是,在第一种情况(常量)中,它是0.3经过转换的,但是这次都是0.1和0.2都转换为float64,但都不是精确的,将它们相加会导致与的距离更大0.3,足以使fmt包的默认舍入为“外观” 。
0.1
0.2