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

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

问题描述

在将 float 转换为 int 时如何避免浮点错误.例如,以下代码打印:0.5499999999999972 当我受伤时期望它打印 0.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

推荐答案

你需要了解一些东西:100.55 是一个十进制数(以十进制基数表示).十进制中的 100.55 是一个有限数,就是:100.55.

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.

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

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....).

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

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.

现在当你说"这个:

x := 100.55

这是一个短变量声明,它将创建一个名为x 并从右侧表达式推断其类型,这是一个浮点文字,因此根据 Go 规范 x 的类型将是 float64.必须转换"浮点文字才能使用 64 位表示(根据 IEEE-754 指定的规则).并且由于 100.55 需要以二进制基数精确表示无限位,因此仅使用 64 位(数字 53),结果将不会(不能)恰好是 100.55(但最接近它的 IEEE-754 格式的 64 位二进制数),即:

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
", x)

100.54999999999999715782905695959925651550292968750000

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

So you are already starting off with a number not being 100.55.

你从中减去 100(float64(int(x)) 就是 100.0):

You subtract 100 from it (float64(int(x)) will be exactly 100.0):

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

0.54999999999999715782905695959925651550292968750000

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

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.

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

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
", x)

结果:

0.55

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

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)

输出:

100.55 $

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

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