Golang将float64转换为int错误 [英] Golang converting float64 to int error

查看:3191
本文介绍了Golang将float64转换为int错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我们将float类型转换为int类型时,如何避免浮点错误。
例如下面的代码打印出来: 0.5499999999999972 当我期望它打印 0.55

  package main 

importfmt

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

输出:
0.5499999999999972
100.55 c>是十进制数(以十进制基数表示)。 100.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 的新变量,并从右边的表达式中推断出它的类型, Go spec x 的类型将是 float64 。为了使用64位(由 IEEE-754 指定的规则)来表示浮点文字,必须进行转换。而且由于 100.55 需要用二进制基数精确地表示无限位,仅使用64位(53位表示数字),结果不会是($) c $ c> 100.55 (但是最接近IEEE-754格式的64位二进制数字),即:

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

100.54999999999999715782905695959925651550292968750000
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 print 0.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 why 1/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. A float64 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 spec x's type will be float64. The floating point literal will have to be "converted" in order to be represented using 64 bits (by rules specified by IEEE-754). And since 100.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 exactly 100.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 exactly 100.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 of 0.55 in a variable of type float64.

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 like

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

Output:

100.55 $

这篇关于Golang将float64转换为int错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆