【问题标题】:Why does 0.1 + 0.2 get 0.3 in Google Go?为什么 0.1 + 0.2 在 Google Go 中得到 0.3?
【发布时间】:2017-02-10 07:25:41
【问题描述】:

只要使用浮点数,0.1 就不能在内存中精确表示,所以我们知道这个值通常出来为 0.10000000000000004。

但是当使用 go 时添加 0.1 和 0.2。 我得到 0.3。

fmt.Println(0.1 + 0.2)
// Output : 0.3

为什么是 0.3 而不是 0.30000000000000004?

【问题讨论】:

  • 确保 Go 不会对表达式进行常量折叠,因为 Go 在编译时使用额外的精度。
  • 感谢新事物!

标签: go precision


【解决方案1】:

这是因为当你打印它时(例如使用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 类型的(非常量)值不同。 数值常量代表任意精度的精确值,不会溢出。

但是在打印ca+cb 的结果时,必须将常量值转换为非常量的类型化值才能传递给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.10.2 都转换为 float64,没有一个是准确的,并且添加它们导致在与0.3 距离较大的数字中,大到足以使用fmt 包的默认舍入形成“视觉外观”。

查看类似/相关问题+答案以了解有关该主题的更多信息:

Why do these two float64s have different values?

How does Go perform arithmetic on constants?

Golang converting float64 to int error

Does go compiler's evaluation differ for constant expression and other expression

Why does adding 0.1 multiple times remain lossless?

Golang Round to Nearest 0.05

Go: Converting float64 to int with multiplier

【讨论】:

  • 谢谢!对不起,我来晚了。它帮助了很多!
猜你喜欢
  • 2011-10-16
  • 1970-01-01
  • 2021-11-04
  • 2020-02-15
  • 2020-10-24
  • 1970-01-01
  • 2012-01-26
  • 2013-03-10
  • 1970-01-01
相关资源
最近更新 更多