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

时间:2015-10-19 03:11:34

标签: go floating-point type-conversion

我想转换一个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上进行这种操作的正确方法是什么?

3 个答案:

答案 0 :(得分:5)

Go spec: Conversions:

  

数字类型之间的转化

     

将浮点数转换为整数时,会丢弃该分数(截断为零)。

所以基本上当你将浮点数转换为整数时,只保留整数部分。

如果您只是想避免因使用有限位表示而产生的错误,只需将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)
}

希望这有帮助!