Golang 将 float64 转换为 int 错误

Golang converting float64 to int error

在将 float 转换为 int 时如何避免浮点错误。 例如下面的代码打印: 0.5499999999999972 when I wound expect it to print 0.55.

package main

import "fmt"

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

Output:
0.5499999999999972

你需要明白一点:100.55是一个十进制数(以十进制表示)。十进制的 100.55 是一个有限数,就是这样:100.55.

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

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

现在当你"say"这个:

x := 100.55

它是一个 short variable declaration,它将创建一个名为 x 的新变量,并从右侧表达式推断其类型,这是一个浮点文字,所以根据 Go 规范 x 的类型将是 float64。浮点文字必须是 "converted" 才能使用 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) 也是二进制表示的无限数,因此您不能在 float64.[=45= 类型的变量中有 0.55 的确切数量]

您可以像往常一样处理数字,但在打印时,将其四舍五入到您选择的小数位。最简单的是使用 fmt.Printf(),并使用动词 %f 指定格式字符串,包括精度:

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

结果:

0.55

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

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

输出:

100.55 $