Go'da float64'ü int türüne dönüştürme


125

Go'da float64 bir int'e nasıl dönüştürülür? strconvPaketin herhangi bir şeyi bir dizeye veya dizeden dönüştürmek için kullanılabileceğini biliyorum , ancak dizge olmayan veri türleri arasında kullanılamaz. fmt.SprintfHerhangi bir şeyi bir dizeye dönüştürmek için kullanabileceğimi ve sonra strconvonu ihtiyacım olan veri türüne çevirebileceğimi biliyorum , ancak bu fazladan dönüştürme biraz hantal görünüyor - bunu yapmanın daha iyi bir yolu var mı?


int(Round(f))float64'ü bir int'e ayarlamak için. Stackoverflow.com/a/62753031/12817546 adresine bakın . float64(i)float64 için bir int ayarlamak için. Stackoverflow.com/a/62737936/12817546 adresine bakın .
Tom J

Yanıtlar:


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

1
@David Grayson, Peki bu dönüşüm Math.Floor (x) ile aynı mı yoksa float64'ün belleğe kaydetme şekli nedeniyle .7'yi düşürüyor mu?
David Larsen

3
@DavidLarsen From the Go spec: "Bir kayan noktalı sayıyı bir tam sayıya dönüştürürken, kesir atılır (sıfıra doğru kesme)". ( Spesifikasyona git )
kvu787

3
Bu tür yayınların Go'da beklenmedik olabilecek bir sorunu vardır (en azından Java'dan geliyorsanız): "Kayan nokta veya karmaşık değerleri içeren tüm sabit olmayan dönüştürmelerde, sonuç türü dönüşümün başarılı olduğu değeri temsil edemiyorsa, ancak sonuç değer uygulamaya bağlıdır. " ( golang.org/ref/spec#Conversions ). Dolayısıyla, sonsuzluk olarak çok büyük bir değeri etkili bir şekilde kullanırsanız ve bunu bir int'e dönüştürürseniz, sonuç tanımsızdır (Java'nın aksine, tamsayı türünün maksimum değeridir).
Jaan

12

Basitçe bir int türüne çevrim şamandırayı keser, eğer sisteminiz 2.0'ı dahili olarak 1.9999999999 olarak temsil ederse, beklediğinizi alamazsınız. Çeşitli printf dönüşümleri bununla ilgilenir ve dönüştürürken sayıyı doğru şekilde yuvarlar. Bu nedenle, daha doğru bir değer elde etmek için, dönüşüm ilk beklediğinizden çok daha karmaşıktır:

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

Go Playground'da Kod


8

Float64'ten int'e ise, bu çalışmalı

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

Çıktılar:

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

İşte oyun alanındaki kod - https://play.golang.org/p/HmFfM6Grqh


Go, en yakın tam sayıya yuvarlamalarda kullanabileceğiniz bir Round işlevine sahiptir: math.Round (-64.99) -65 çıktı verir.
AHonarmand

2

Sen kullanabilirsiniz int()dönüştürmek fonksiyonu float64bir tip veri int. Benzer şekilde kullanabilirsinizfloat64()

Misal:

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

Doğru yuvarlama muhtemelen istenir.

Bu nedenle math.Round () sizin hızlı (!) Arkadaşınızdır. Fmt.Sprintf ve strconv.Atois () ile yaklaşımlar, doğru şekilde yuvarlatılmış int değerleri haline gelmesi amaçlanan float64 değerlerinden oluşan bir matris ile testlerime göre 2 büyüklük sırası daha yavaştı.

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 () float64 değeri döndürüyor, ancak daha sonra int () uygulandığında, şu ana kadar herhangi bir uyumsuzluk bulamadım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.