Converti un float64 in un int in Go


124

Come si converte un float64 in un int in Go? So che il strconvpacchetto può essere utilizzato per convertire qualsiasi cosa in o da una stringa, ma non tra tipi di dati in cui uno non è una stringa. So di poterlo usare fmt.Sprintfper convertire qualsiasi cosa in una stringa e poi strconvnel tipo di dati di cui ho bisogno, ma questa conversione extra sembra un po 'goffa: c'è un modo migliore per farlo?


int(Round(f))per impostare un float64 su un int. Vedi stackoverflow.com/a/62753031/12817546 . float64(i)per impostare un int a float64. Vedi stackoverflow.com/a/62737936/12817546 .
Tom J

Risposte:


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

1
@David Grayson, quindi questa conversione è la stessa di Math.Floor (x) o fa cadere il .7 a causa del modo in cui float64 lo salva in memoria?
David Larsen

3
@DavidLarsen Dalla specifica Go: "Quando si converte un numero a virgola mobile in un intero, la frazione viene scartata (troncamento verso zero)". ( Vai alle specifiche )
kvu787

3
Tali cast hanno un problema in Go che può essere inaspettato (almeno se provieni da Java): "In tutte le conversioni non costanti che coinvolgono valori a virgola mobile o complessi, se il tipo di risultato non può rappresentare il valore la conversione ha successo ma il risultato il valore dipende dall'implementazione. " ( golang.org/ref/spec#Conversions ). Quindi, se si utilizza un valore molto grande effettivamente come infinito e lo si converte in un int, il risultato non è definito (a differenza di Java, dove è il valore massimo del tipo intero).
Jaan

12

Il semplice casting su un int tronca il float, che se il tuo sistema rappresenta internamente 2.0 come 1.9999999999, non otterrai ciò che ti aspetti. Le varie conversioni printf si occupano di questo e arrotondano correttamente il numero durante la conversione. Quindi, per ottenere un valore più accurato, la conversione è ancora più complicata di quanto potresti aspettarti:

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

Codice su Go Playground


8

Se è semplicemente da float64 a int, dovrebbe funzionare

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

Uscite:

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

Ecco il codice nel playground: https://play.golang.org/p/HmFfM6Grqh


Go ha una funzione Round che puoi usare che arrotonda al numero intero più vicino: math.Round (-64.99) restituirà -65.
AHonarmand

2

È possibile utilizzare la int()funzione per convertire i float64dati di tipo in un file int. Allo stesso modo puoi usarefloat64()

Esempio:

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
} 

2

Probabilmente si desidera un arrotondamento corretto.

Quindi math.Round () è il tuo amico veloce (!). Gli approcci con fmt.Sprintf e strconv.Atois () erano 2 ordini di grandezza più lenti secondo i miei test con una matrice di valori float64 che dovevano diventare valori int arrotondati correttamente.

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 () restituisce un valore float64 ma con int () applicato successivamente, non sono riuscito a trovare alcuna mancata corrispondenza finora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.