213

How does one convert a float64 to an int in Go? I know the strconv package can be used to convert anything to or from a string, but not between data types where one isn't a string. I know I can use fmt.Sprintf to convert anything to a string, and then strconv it to the data type I need, but this extra conversion seems a bit clumsy - is there a better way to do this?

Charles
  • 50,943
  • 13
  • 104
  • 142
Chris Bunch
  • 87,773
  • 37
  • 126
  • 127
  • 1
    `int(Round(f))` to set a float64 to an int. See https://stackoverflow.com/a/62753031/12817546. `float64(i)` to set an int to a float64. See https://stackoverflow.com/a/62737936/12817546. –  Jul 08 '20 at 10:36

5 Answers5

315
package main
import "fmt"
func main() {
  var x float64 = 5.7
  var y int = int(x)
  fmt.Println(y)  // outputs "5"
}
David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • 1
    @David Grayson, So is this conversion the same as Math.Floor(x) or does it drop the .7 because of the way the float64 saves it in memory? – David Larsen Oct 29 '14 at 13:12
  • 15
    @DavidLarsen From the Go spec: "When converting a floating-point number to an integer, the fraction is discarded (truncation towards zero)". ([Go spec](http://golang.org/ref/spec#Conversions)) – kvu787 Nov 26 '14 at 17:48
  • 9
    Such casts have a problem in Go that can be unexpected (at least if you come from Java): "In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent." (https://golang.org/ref/spec#Conversions). So if you use a very large value effectively as an infinity, and you convert it into an int, the result is undefined (unlike Java, where it is the maximal value of the integer type). – Jaan May 27 '16 at 14:37
  • just an update. looks like var y = int(x) is suffice with new GO version. – JavaQuest Dec 28 '20 at 14:45
19

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

David Dooling
  • 674
  • 7
  • 6
17

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.

scaszoo
  • 191
  • 1
  • 4
6

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

Peanuts
  • 352
  • 3
  • 6
  • 2
    Go has a Round function you can use that rounds to the nearest integer: math.Round(-64.99) will output -65. – AHonarmand May 24 '19 at 16:57
4

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
} 
Nik
  • 2,885
  • 2
  • 25
  • 25
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81