Golang将float64转换为int错误

时间:2016-03-17 06:13:55

标签: go floating-point precision

将float转换为int时,如何避免浮点错误。 例如,以下代码打印:0.5499999999999972当我受伤时,希望它打印0.55

package main

import "fmt"

func main() {
    x := 100.55
    fmt.Println(x - float64(int(x)))    
}

Output:
0.5499999999999972

1 个答案:

答案 0 :(得分:6)

您需要了解一些事情:100.55是一个十进制数字(以十进制基数表示)。十进制中的100.55是一个有限数字,正是这样:100.55

计算机一般以二进制表示形式存储数字。数字100.55不能用有限的二进制数表示:100.55是二进制表示中的无限数字(同样的原因1/3无法用有限的数字表示十进制数,它是一个无穷无尽的序列:0.333333333....)。

但Go(与任何其他语言一样)使用IEEE-754标准存储float64类型,这是一种有限的二进制表示。 float64值使用内存中的64位来描述数字,其中53位用于描述数字,11位用于指数。

现在当你"说"这样:

x := 100.55

它是一个short variable declaration,它将创建一个名为x的新变量,并从右侧表达式推断其类型,这是一个浮点文字,所以Go规范x '类型将是float64。浮点字面值必须进行转换"为了用64位表示(由IEEE-754指定的规则)。并且由于100.55要求无限位以二进制基数精确表示,因此仅使用64位(数字为53),结果将不会(不能)正好100.55(但是64位)最接近它的IEEE-754格式的二进制数,即:

x := 100.55
fmt.Printf("%.50f\n", x)

100.54999999999999715782905695959925651550292968750000

所以你已经开始使用的数字不是100.55

您从中减去100float64(int(x))将完全100.0):

x = x - float64(int(x))
fmt.Printf("%.50f\n", x)

0.54999999999999715782905695959925651550292968750000

你能做些什么?真的没什么。您期望的结果(0.55)在二进制表示中也是无限数字,因此您不能在0.55类型的变量中具有确切数量的float64

您可以做的是正常使用数字,但是当您打印它时,将其四舍五入到您选择的小数位。最简单的方法是使用fmt.Printf(),并使用动词%f指定格式字符串,包括精度:

fmt.Printf("%.2f\n", x)

结果:

0.55

另一种选择是避免使用浮点数。例如。如果你要代表美元金额,你可以"乘以"所有值均由100表示,并表示为美分(1 $ * 100),这是一个整数。只有当您需要将结果打印为USD时,才能打印类似

的内容
cents := 10055
fmt.Printf("%d.%d $", cents/100, cents%100)

输出:

100.55 $