Golang将float64转换为int错误 [英] Golang converting float64 to int error
问题描述
例如下面的代码打印出来:
0.5499999999999972
当我期望它打印 0.55
。package main
(但是最接近IEEE-754格式的64位二进制数字),即:
importfmt
func main(){
x:= 100.55
fmt.Println(x - float64(int(x)))
}
输出:
0.5499999999999972
$您需要了解一些内容:100.55 $ c $> c>是十进制数(以十进制基数表示)。
的新变量,并从右边的表达式中推断出它的类型, Go spec100.55
在十进制中是一个有限数字,正是这个:100.55
。
计算机一般以二进制表示存储数字。数字
100.55
不能用有限的二进制数表示:100.55
是一个无限数字在二进制表示中(同样的原因,为什么1/3
不能用一个有限的十进制数表示,这是一个无尽的序列:0.333333333 ....
)。
$ b 但是Go(像任何其他语言一样)使用> float64
IEEE-754 标准,这是一个有限的二进制 表示。float64
值在内存中使用64位来描述数字,其中53位用于描述数字,11位用于指数。 b
$ b现在当你说这个时:
x:= 100.55
这是 x
x
的类型将是float64
。为了使用64位(由IEEE-754
指定的规则)来表示浮点文字,必须进行转换。而且由于100.55
需要用二进制基数精确地表示无限位,仅使用64位(53位表示数字),结果不会是($) c $ c> 100.55
x:= 100.55
fmt.Printf(%。50f\\\
,x)
100.54999999999999715782905695959925651550292968750000
$ c $所以你已经开始了一个不是100.55
的数字。
您从中减去
100
(float64(int(x))
将会正好100.0
):
x = x - float64(int (x))
fmt.Printf(%。50f \\\
,x)
0.54999999999999715782905695959925651550292968750000
你能做些什么呢?真的没什么。你期望得到的结果(
0.55
)在二进制表示中也是一个无限的数字,所以你不能有一个确切的数字0.55
在一个float64
类型的变量中。
你可以做的是使用正常的数字,但是当您打印它时,将其舍入到您选择的小数位。最简单的方法是使用
fmt.Printf()
,并使用动词%f
指定格式字符串,包括精度:
fmt.Printf(%。2f\\\
,x)
:
0.55
另一个选择是避免使用浮点数。例如。如果您要表示美元金额,则可以将所有值乘以
100
,并将金额表示为美分(1 $ * 100),这是一个整数。只有当您需要以美元打印结果时,才可以打印如下所示的内容:
cents:= 10055
fmt。 Printf(%d。%d $,美分/ 100,美分%100)
100.55 $
How can I avoid floating point errors when converting float's to int's. For example the following code prints:
0.5499999999999972
when I wound expect it to print0.55
.package main import "fmt" func main() { x := 100.55 fmt.Println(x - float64(int(x))) } Output: 0.5499999999999972
解决方案You need to understand something:
100.55
is a decimal number (presented in decimal radix).100.55
in decimal is a finite number and is exactly this:100.55
.Computers in general store numbers in binary representation. The number
100.55
cannot be represented with a finite binary number:100.55
is an infinite number in binary representation (same reason why1/3
cannot be represented with a finite decimal number, it is an endless sequence:0.333333333....
).But Go (like any other language) stores
float64
types using the IEEE-754 standard, which is a finite binary representation. Afloat64
value uses 64 bits in memory to describe the number, of which 53 bits are used to describe the digits and 11 bits are used for the exponent.Now when you "say" this:
x := 100.55
It is a short variable declaration which will create a new variable named
x
and infer its type from the right hand side expression which is a floating point literal, so by the Go specx
's type will befloat64
. The floating point literal will have to be "converted" in order to be represented using 64 bits (by rules specified byIEEE-754
). And since100.55
would require infinite bits to be represented precisely in binary radix, by using only 64 bits (53 for the digits) the result will not (cannot) be exactly100.55
(but a 64-bit binary number in IEEE-754 format that is closest to it), which is:x := 100.55 fmt.Printf("%.50f\n", x) 100.54999999999999715782905695959925651550292968750000
So you are already starting off with a number not being
100.55
.You subtract
100
from it (float64(int(x))
will be exactly100.0
):x = x - float64(int(x)) fmt.Printf("%.50f\n", x) 0.54999999999999715782905695959925651550292968750000
What can you do about it? Nothing really. The result you expect (
0.55
) is also an infinite number in binary representation, so you can't have an exact number of0.55
in a variable of typefloat64
.What you can do is work with the number as normal, but when you print it, round it to decimal places of your choice. The easiest is to use
fmt.Printf()
, and specify a format string using the verb%f
including the precision:fmt.Printf("%.2f\n", x)
Result:
0.55
Another option is to avoid using floating point numbers. E.g. if you were to represent USD amounts, you could "multiply" all your values by
100
and represent amounts as cents (1$*100) which is an integer. Only if you need to print the result as USD, you could print something likecents := 10055 fmt.Printf("%d.%d $", cents/100, cents%100)
Output:
100.55 $
这篇关于Golang将float64转换为int错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!