为什么 0.1 + 0.2 在 Google Go 中得到 0.3?
Why does 0.1 + 0.2 get 0.3 in Google Go?
只要是用浮点数,0.1在内存中是无法准确表示的,所以我们知道这个值通常出来是0.100000000000000004。
但是用go的时候要加上0.1和0.2。
我得到 0.3.
fmt.Println(0.1 + 0.2)
// Output : 0.3
为什么出来的是 0.3 而不是 0.30000000000000004?
这是因为当你打印它时(例如使用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
首先我们使用 constants,因为这与使用 float64
类型的 (non-constant) 值不同。 数值常量表示任意精度的精确值,不会溢出。
但是当打印 ca+cb
的结果时,常量值必须转换为 non-constant,键入的值才能传递给 fmt.Println()
。该值将是 float64
类型,不能准确表示 0.3
。但是 fmt.Println()
会将其四舍五入为 ~16 位小数,即 0.3
。但是当我们明确声明我们希望它以 20 位数字显示时,我们会发现它并不准确。请注意,只有 0.3
会被转换为 float64
,因为常量运算 0.1+0.2
将由编译器计算(在编译时)。
接下来我们从 float64
类型的变量开始,毫不奇怪,输出不完全是 0.3
,但这次即使使用默认舍入,我们得到的结果也不同于 0.3
。之所以这样是因为第一种情况(常量)是0.3
被转换了,但是这次0.1
和0.2
都被转换成了float64
,none 其中是精确的,将它们相加会导致与 0.3
的距离更大,大到足以使 "visual appearance" 具有 fmt
包的默认舍入。
查看类似/相关问题+答案以了解有关该主题的更多信息:
Why does adding 0.1 multiple times remain lossless?
只要是用浮点数,0.1在内存中是无法准确表示的,所以我们知道这个值通常出来是0.100000000000000004。
但是用go的时候要加上0.1和0.2。 我得到 0.3.
fmt.Println(0.1 + 0.2)
// Output : 0.3
为什么出来的是 0.3 而不是 0.30000000000000004?
这是因为当你打印它时(例如使用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
首先我们使用 constants,因为这与使用 float64
类型的 (non-constant) 值不同。 数值常量表示任意精度的精确值,不会溢出。
但是当打印 ca+cb
的结果时,常量值必须转换为 non-constant,键入的值才能传递给 fmt.Println()
。该值将是 float64
类型,不能准确表示 0.3
。但是 fmt.Println()
会将其四舍五入为 ~16 位小数,即 0.3
。但是当我们明确声明我们希望它以 20 位数字显示时,我们会发现它并不准确。请注意,只有 0.3
会被转换为 float64
,因为常量运算 0.1+0.2
将由编译器计算(在编译时)。
接下来我们从 float64
类型的变量开始,毫不奇怪,输出不完全是 0.3
,但这次即使使用默认舍入,我们得到的结果也不同于 0.3
。之所以这样是因为第一种情况(常量)是0.3
被转换了,但是这次0.1
和0.2
都被转换成了float64
,none 其中是精确的,将它们相加会导致与 0.3
的距离更大,大到足以使 "visual appearance" 具有 fmt
包的默认舍入。
查看类似/相关问题+答案以了解有关该主题的更多信息:
Why does adding 0.1 multiple times remain lossless?