[英]Go: Converting float64 to int with multiplier
我想转换一个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上进行这种操作的正确方法是什么?
数字类型之间的转换
将浮点数转换为整数时,将丢弃该分数(截断为零)。
所以基本上当你将浮点数转换为整数时,只保留整数部分。
如果您只是想避免因使用有限位表示而产生的错误,只需在将数字转换为int
之前将数字加0.5
即可。 无需外部库或函数调用(来自标准库)。
由于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)
}
正如威尔所提到的,这归结为浮动在各种平台上的表现方式。 基本上你需要对浮点数进行舍入而不是让默认的截断行为发生。 这没有标准的库函数,可能是因为有很多可能的行为,实现起来很简单。
如果你知道你总是有所描述类型的错误,你所需的值(130099000)略低于(1299.999999)你可以使用数学库的Ceil
函数:
f := 1.29999
n := math.Ceil(f*1000)
但是,如果您有不同类型的浮动错误并想要更通用的排序行为? 使用数学库的Modf
函数将浮点值与小数点分开:
f := 1.29999
f1,f2 := math.Modf(f*1000)
n := int(f1) // n = 1299
if f2 > .5 {
n++
}
fmt.Println(n)
您可以自己在游乐场中运行此代码的稍微更通用的版本。
在大多数编程语言中,这通常可能是浮点问题,尽管有些实现与其他编程语言不同。 我不会在这里讨论复杂的问题,但是大多数语言通常采用“十进制”方法作为标准库或第三方库来获得更精确的。
例如,我发现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)
}
希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.