我想转换一个float64
号码,让我们说1.003
到1003
(整数类型)。我的实现只是将float64
与1000
相乘并将其转换为int
。
package main
import "fmt"
func main() {
var f float64 = 1.003
fmt.Println(int(f * 1000))
}
但是当我运行该代码时,我得到的是1002
而不是1003
。因为Go会自动将1.003
存储为变量中的1.002999...
。在Golang上进行这种操作的正确方法是什么?
答案 0 :(得分:5)
数字类型之间的转化
将浮点数转换为整数时,会丢弃该分数(截断为零)。
所以基本上当你将浮点数转换为整数时,只保留整数部分。
如果您只是想避免因使用有限位表示而产生的错误,只需将0.5
添加到该数字,然后再将其转换为int
。无需外部库或函数调用(来自标准库)。
由于float -> int
转换没有舍入,但保留整数部分,这将为您提供所需的结果。考虑到可能的更小和更大的代表性:
1002.9999 + 0.5 = 1003.4999; integer part: 1003
1003.0001 + 0.5 = 1003.5001; integer part: 1003
所以简单地写一下:
var f float64 = 1.003
fmt.Println(int(f * 1000 + 0.5))
将其包装成一个函数:
func toint(f float64) int {
return int(f + 0.5)
}
// Using it:
fmt.Println(toint(f * 1000))
在Go Playground上试用。
注意:强>
如果是负数,请小心使用!例如,如果您的值为-1.003
,那么您可能希望结果为-1003
。但是如果你向它添加0.5
:
-1002.9999 + 0.5 = -1002.4999; integer part: -1002
-1003.0001 + 0.5 = -1002.5001; integer part: -1002
因此,如果您有负数,则必须:
0.5
而不是添加0.5
但从结果1
将此结合到我们的辅助函数中:
func toint(f float64) int {
if f < 0 {
return int(f - 0.5)
}
return int(f + 0.5)
}
答案 1 :(得分:2)
正如威尔所提到的,这归结为浮动在各种平台上的表现方式。基本上你需要对浮点数进行舍入而不是让默认的截断行为发生。这没有标准的库函数,可能是因为有很多可能的行为,并且实现起来很简单。
如果您知道自己总是有所描述类型的错误,那么您所需要的值(1299.999999)(1300.0099)可以使用数学库{{1}功能:
Ceil
但是如果你有不同类型的浮动错误并想要更通用的排序行为?使用数学库的f := 1.29999
n := math.Ceil(f*1000)
函数将浮点值除以小数点:
Modf
您可以自己在playground中运行此代码稍微更通用的版本。
答案 2 :(得分:0)
在大多数编程语言中,这可能是浮点问题,尽管有些实现与其他编程语言不同。我不会在这里进入复杂的问题,但大多数语言通常都有一个&#34;十进制&#34;无论是作为标准库还是第三方库,都可以获得更好的精度。
例如,我发现inf.v0包非常有用。该库的基础是一个Dec
结构,它包含指数和整数值。因此,它可以1.003
作为1003 * 10^-3
。请参阅下面的示例:
package main
import (
"fmt"
"gopkg.in/inf.v0"
)
func main() {
// represents 1003 * 10^-3
someDec := inf.NewDec(1003, 3)
// multiply someDec by 1000 * 10^0
// which translates to 1003 * 10^-3 * 1000 * 10^0
someDec.Mul(someDec, inf.NewDec(1000, 0))
// inf.RoundHalfUp rounds half up in the 0th scale, eg. 0.5 rounds to 1
value, ok := someDec.Round(someDec, 0, inf.RoundHalfUp).Unscaled()
fmt.Println(value, ok)
}
希望这有帮助!