繁体   English   中英

Go:使用乘数将float64转换为int

[英]Go: Converting float64 to int with multiplier

我想转换一个float64号码,比方说1.0031003 (整数类型)。 我的实现只是将float641000相乘并将其转换为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM