为什么0.1 + 0.2在Google Go中获得0.3?

Int*_*ral 6 precision go

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

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

fmt.Println(0.1 + 0.2)
// Output : 0.3
Run Code Online (Sandbox Code Playgroud)

为什么0.3出来而不是0.30000000000000004?

icz*_*cza 6

这是因为当你打印它时(例如使用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)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

0.3
0.29999999999999998890
0.30000000000000004
0.30000000000000004441
Run Code Online (Sandbox Code Playgroud)

首先我们使用常量,因为这与使用类型的(非常量)值不同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.

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

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

Go如何对常量执行算术运算?

Golang将float64转换为int错误

对于常量表达式和其他表达式,编译器的评估是否有所不同

为什么多次添加0.1会保持无损?

Golang Round最近的0.05

Go:使用乘数将float64转换为int