在Go中将float64转换为int

213

如何在Go中将float64转换为int?我知道strconv包可以用于将任何东西转换为字符串或从字符串转换,但不能在一个不是字符串的数据类型之间进行转换。我知道可以使用fmt.Sprintf将任何内容转换为字符串,然后strconv它到我需要的数据类型,但这个额外的转换似乎有点笨拙 - 是否有更好的方法来做到这一点?


1
int(Round(f)) 将 float64 转换为 int。请参见 https://dev59.com/XlsW5IYBdhLWcg3wT155#62753031。`float64(i)` 将 int 转换为 float64。请参见 https://dev59.com/e2Yr5IYBdhLWcg3w0taE#62737936。 - user12817546
5个回答

315
package main
import "fmt"
func main() {
  var x float64 = 5.7
  var y int = int(x)
  fmt.Println(y)  // outputs "5"
}

1
@David Grayson,那么这个转换和Math.Floor(x)一样吗?还是因为float64在内存中的保存方式而丢弃了.7? - David Larsen
15
从Go规范中可以得知,将浮点数转换为整数时,小数部分会被舍弃(朝向0的截断)。 - kvu787
9
在Go语言中,这种类型转换存在一个问题,可能会出现意外情况(至少对于从Java转过来的人是这样):“涉及浮点数或复数值的所有非常量转换,如果结果类型无法表示该值,则转换成功,但结果值取决于实现。”(https://golang.org/ref/spec#Conversions)。因此,如果您将一个非常大的值用作无穷大,并将其转换为int类型,结果是未定义的(与Java不同,在Java中,它是整数类型的最大值)。 - Jaan
只是一个更新。看起来在新的GO版本中,var y = int(x)就足够了。 - JavaQuest

19

简单地将浮点数强制转换为整数会截断该浮点数,如果你的系统内部将2.0表示为1.9999999999,则你将无法获得你期望的结果。各种printf转换可以处理这个问题,并在转换时正确四舍五入。因此,为了获得更精确的值,转换比你最初期望的要更加复杂:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    floats := []float64{1.9999, 2.0001, 2.0}
    for _, f := range floats {
        t := int(f)
        s := fmt.Sprintf("%.0f", f)
        if i, err := strconv.Atoi(s); err == nil {
            fmt.Println(f, t, i)
        } else {
            fmt.Println(f, t, err)
        }
    }
}

Go Playground上编写代码


1
或者直接使用 math.Round() - Ted Brownlow
1
现在这是最好的方法,但是math.Round是在Go 1.10中引入的,该版本发布于上述答案发布两年后。 - David Dooling

17

正确的四舍五入可能是您想要的。

因此,math.Round() 是您的快速(!)朋友。根据我在一个由 float64 值组成的矩阵上进行的测试,使用 fmt.Sprintf 和 strconv.Atois() 方法的处理速度慢了两个数量级,而该矩阵旨在将这些值正确地舍入为 int 值。

package main
import (
    "fmt"
    "math"
)
func main() {
    var x float64 = 5.51
    var y float64 = 5.50
    var z float64 = 5.49
    fmt.Println(int(math.Round(x)))  // outputs "6"
    fmt.Println(int(math.Round(y)))  // outputs "6"
    fmt.Println(int(math.Round(z)))  // outputs "5"
}

math.Round() 返回一个 float64 值,但是在之后应用 int() 函数后,我目前还没有发现任何不匹配的地方。


6

如果只是从float64转换为int,那么这应该可行。

package main

import (
    "fmt"
)

func main() {
    nf := []float64{-1.9999, -2.0001, -2.0, 0, 1.9999, 2.0001, 2.0}

    //round
    fmt.Printf("Round : ")
    for _, f := range nf {
        fmt.Printf("%d ", round(f))
    }
    fmt.Printf("\n")

    //rounddown ie. math.floor
    fmt.Printf("RoundD: ")
    for _, f := range nf {
        fmt.Printf("%d ", roundD(f))
    }
    fmt.Printf("\n")

    //roundup ie. math.ceil
    fmt.Printf("RoundU: ")
    for _, f := range nf {
        fmt.Printf("%d ", roundU(f)) 
    }
    fmt.Printf("\n")

}

func roundU(val float64) int {
    if val > 0 { return int(val+1.0) }
    return int(val)
}

func roundD(val float64) int {
    if val < 0 { return int(val-1.0) }
    return int(val)
}

func round(val float64) int {
    if val < 0 { return int(val-0.5) }
    return int(val+0.5)
}

输出:

Round : -2 -2 -2 0 2 2 2 
RoundD: -2 -3 -3 0 1 2 2 
RoundU: -1 -2 -2 0 2 3 3 

以下是游乐场中的代码 - https://play.golang.org/p/HmFfM6Grqh


2
Go语言提供了一个Round函数,可以将数字四舍五入到最近的整数: math.Round(-64.99) 的输出结果为 -65。 - AHonarmand

4
你可以使用int()函数将float64类型的数据转换为int。同样,你也可以使用float64()函数。
示例:
func check(n int) bool { 
    // count the number of digits 
    var l int = countDigit(n)
    var dup int = n 
    var sum int = 0 

    // calculates the sum of digits 
    // raised to power 
    for dup > 0 { 
        **sum += int(math.Pow(float64(dup % 10), float64(l)))** 
        dup /= 10 
    } 

    return n == sum
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接