在Go中将float64转换为int

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

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

Simply casting to an int truncates the float, which if your system internally represent 2.0 as 1.9999999999, you will not get what you expect. The various printf conversions deal with this and properly round the number when converting. So to get a more accurate value, the conversion is even more complicated than you might first expect:

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)
}
}
}

Code on Go Playground

If its simply from float64 to int, this should work

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)
}

Outputs:

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

Here's the code in the playground - https://play.golang.org/p/HmFfM6Grqh

You can use int() function to convert float64 type data to an int. Similarly you can use float64()

Example:

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
}

Correct rounding is likely desired.

Therefore math.Round() is your quick(!) friend. Approaches with fmt.Sprintf and strconv.Atois() were 2 orders of magnitude slower according to my tests with a matrix of float64 values that were intended to become correctly rounded int values.

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() does return a float64 value but with int() applied afterwards, I couldn't find any mismatches so far.