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
的数字。
你从中减去 100
(float64(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 $
在将 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
的数字。
你从中减去 100
(float64(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 $