Konwertuj float64 na int w Go


124

Jak przekonwertować float64 na int w Go? Wiem, że strconvpakiet może służyć do konwertowania czegokolwiek na lub z ciągu, ale nie między typami danych, w których jeden nie jest ciągiem. Wiem, że mogę użyć fmt.Sprintfdo przekonwertowania czegokolwiek na ciąg, a następnie strconvna typ danych, którego potrzebuję, ale ta dodatkowa konwersja wydaje się nieco niezdarna - czy jest lepszy sposób na zrobienie tego?


int(Round(f))aby ustawić float64 na int. Zobacz stackoverflow.com/a/62753031/12817546 . float64(i)aby ustawić int na float64. Zobacz stackoverflow.com/a/62737936/12817546 .
— Tom J

Odpowiedzi:


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, Czy więc ta konwersja jest taka sama, jak Math.Floor (x), czy też upuszcza .7 ze względu na sposób, w jaki float64 zapisuje go w pamięci?
— David Larsen

3
@DavidLarsen Ze specyfikacji Go: "Podczas konwersji liczby zmiennoprzecinkowej na liczbę całkowitą ułamek jest odrzucany (obcięcie w kierunku zera)". ( Idź do specyfikacji )
— kvu787

3
Takie rzutowania mają problem w Go, który może być nieoczekiwany (przynajmniej jeśli pochodzisz z Javy): „We wszystkich niestandardowych konwersjach obejmujących wartości zmiennoprzecinkowe lub zespolone, jeśli typ wyniku nie może reprezentować wartości, konwersja się powiedzie, ale wynik wartość zależy od implementacji ”. ( golang.org/ref/spec#Conversions ). Więc jeśli efektywnie użyjesz bardzo dużej wartości jako nieskończoności i przekonwertujesz ją na int, wynik jest niezdefiniowany (w przeciwieństwie do Java, gdzie jest to maksymalna wartość typu całkowitego).
— Jaan

12

Zwykłe rzutowanie na int obcina liczbę zmiennoprzecinkową, która jeśli Twój system wewnętrznie reprezentuje 2.0 jako 1.9999999999, nie uzyskasz tego, czego oczekujesz. Różne konwersje printf radzą sobie z tym i odpowiednio zaokrąglają liczbę podczas konwersji. Aby uzyskać dokładniejszą wartość, konwersja jest jeszcze bardziej skomplikowana, niż można by się było spodziewać:

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


8

Jeśli to po prostu od float64 do int, to powinno działać

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

Wyjścia:

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

Oto kod na placu zabaw - https://play.golang.org/p/HmFfM6Grqh


Go ma funkcję Round, której możesz użyć, która zaokrągla do najbliższej liczby całkowitej: math.Round (-64,99) daje wynik -65.
— AHonarmand

2

Możesz użyć int()funkcji, aby przekonwertować float64dane typu na plik int. Podobnie możesz użyćfloat64()

Przykład:

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

Prawdopodobnie pożądane jest prawidłowe zaokrąglenie.

Dlatego math.Round () jest twoim szybkim (!) Przyjacielem. Podejścia z fmt.Sprintf i strconv.Atois () były o 2 rzędy wielkości wolniejsze, zgodnie z moimi testami z macierzą wartości float64, które miały stać się poprawnie zaokrąglonymi wartościami 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 () zwraca wartość float64, ale po zastosowaniu funkcji int () nie mogłem do tej pory znaleźć żadnych niezgodności.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.