Konvertieren Sie ein float64 in ein int in Go

124

Wie konvertiert man ein float64 in ein int in Go? Ich weiß, dass das strconvPaket verwendet werden kann, um etwas in oder von einer Zeichenfolge zu konvertieren, aber nicht zwischen Datentypen, bei denen es sich nicht um eine Zeichenfolge handelt. Ich weiß, dass ich damit fmt.Sprintfalles in eine Zeichenfolge konvertieren kann und dann strconvin den Datentyp, den ich benötige, aber diese zusätzliche Konvertierung scheint etwas umständlich zu sein - gibt es einen besseren Weg, dies zu tun?

Chris Bunch
quelle
int(Round(f))um einen float64 auf einen int zu setzen. Siehe stackoverflow.com/a/62753031/12817546 . float64(i)um ein int auf ein float64 zu setzen. Siehe stackoverflow.com/a/62737936/12817546 .
Tom J

Antworten:

200
package main
import "fmt"
func main() {
  var x float64 = 5.7
  var y int = int(x)
  fmt.Println(y)  // outputs "5"
}
David Grayson
quelle
1
@ David Grayson, ist diese Konvertierung also dieselbe wie Math.Floor (x) oder wird die .7 gelöscht, weil float64 sie im Speicher speichert?
David Larsen
3
@DavidLarsen From the Go-Spezifikation: "Beim Konvertieren einer Gleitkommazahl in eine Ganzzahl wird der Bruch verworfen (Kürzung gegen Null)." ( Go spec )
kvu787
3
Solche Casts haben in Go ein Problem, das unerwartet sein kann (zumindest wenn Sie aus Java stammen): "Wenn bei allen nicht konstanten Konvertierungen mit Gleitkomma- oder komplexen Werten der Ergebnistyp nicht den Wert darstellen kann, ist die Konvertierung erfolgreich, sondern das Ergebnis Wert ist implementierungsabhängig. " ( golang.org/ref/spec#Conversions ). Wenn Sie also einen sehr großen Wert effektiv als Unendlichkeit verwenden und ihn in ein int konvertieren, ist das Ergebnis undefiniert (im Gegensatz zu Java, wo es der Maximalwert des Integer-Typs ist).
Jaan
11

Durch einfaches Casting in ein Int wird der Float abgeschnitten. Wenn Ihr System intern 2.0 als 1.9999999999 darstellt, erhalten Sie nicht das, was Sie erwarten. Die verschiedenen printf-Konvertierungen kümmern sich darum und runden die Zahl beim Konvertieren richtig ab. Um einen genaueren Wert zu erhalten, ist die Konvertierung noch komplizierter als zunächst angenommen:

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 Spielplatz

David Dooling
quelle
8

Wenn es einfach von float64 bis int ist, sollte dies funktionieren

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

Ausgänge:

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

Hier ist der Code auf dem Spielplatz - https://play.golang.org/p/HmFfM6Grqh

Erdnüsse
quelle
Go hat eine Rundungsfunktion, mit der Sie auf die nächste Ganzzahl runden können: math.Round (-64.99) gibt -65 aus.
AHonarmand
2

Sie können mit int()Funktion konvertieren float64Typ Daten ein int. Ebenso können Sie verwendenfloat64()

Beispiel:

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
} 
Codemaker
quelle
2

Eine korrekte Rundung ist wahrscheinlich erwünscht.

Deshalb ist math.Round () dein schneller (!) Freund. Ansätze mit fmt.Sprintf und strconv.Atois () waren nach meinen Tests mit einer Matrix von float64-Werten, die korrekt gerundete int-Werte werden sollten, 2 Größenordnungen langsamer.

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 () gibt zwar einen float64-Wert zurück, aber mit int (), das danach angewendet wird, konnte ich bisher keine Fehlanpassungen finden.

Scaszoo
quelle