Chuyển đổi float64 thành int trong Go


124

Làm cách nào để chuyển đổi float64 thành int trong Go? Tôi biết strconvgói có thể được sử dụng để chuyển đổi bất kỳ thứ gì thành hoặc từ một chuỗi, nhưng không phải giữa các kiểu dữ liệu mà một không phải là chuỗi. Tôi biết tôi có thể sử dụng fmt.Sprintfđể chuyển đổi bất kỳ thứ gì thành chuỗi và sau strconvđó thành kiểu dữ liệu tôi cần, nhưng việc chuyển đổi bổ sung này có vẻ hơi vụng về - có cách nào tốt hơn để thực hiện điều này không?


int(Round(f))để đặt float64 thành int. Xem stackoverflow.com/a/62753031/12817546 . float64(i)để đặt một int thành float64. Xem stackoverflow.com/a/62737936/12817546 .
Tom J

Câu trả lời:


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, Vậy chuyển đổi này có giống với Math.Floor (x) hay nó giảm .7 do cách float64 lưu nó vào bộ nhớ?
David Larsen

3
@DavidLarsen From the Go spec: "Khi chuyển đổi một số dấu phẩy động thành một số nguyên, phân số sẽ bị loại bỏ (cắt bớt về 0)". ( Đi thông số kỹ thuật )
kvu787

3
Những lần chuyển kiểu như vậy có một vấn đề trong Go có thể không mong muốn (ít nhất là nếu bạn đến từ Java): "Trong tất cả các chuyển đổi không liên tục liên quan đến dấu phẩy động hoặc giá trị phức, nếu loại kết quả không thể đại diện cho giá trị thì chuyển đổi thành công nhưng kết quả giá trị phụ thuộc vào việc triển khai. " ( golang.org/ref/spec#Conversions ). Vì vậy, nếu bạn sử dụng một giá trị rất lớn một cách hiệu quả như một giá trị vô cùng và bạn chuyển đổi nó thành một số nguyên, kết quả là không xác định (không giống như Java, trong đó nó là giá trị lớn nhất của kiểu số nguyên).
Jaan

12

Chỉ cần truyền tới một int sẽ cắt bớt float, nếu hệ thống của bạn biểu thị nội bộ 2.0 là 1.9999999999, bạn sẽ không nhận được những gì bạn mong đợi. Các chuyển đổi printf khác nhau giải quyết vấn đề này và làm tròn số đúng cách khi chuyển đổi. Vì vậy, để có được giá trị chính xác hơn, việc chuyển đổi thậm chí còn phức tạp hơn những gì bạn có thể mong đợi ban đầu:

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

Nếu nó chỉ đơn giản là từ float64 thành int, điều này sẽ hoạt động

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

Kết quả đầu ra:

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

Đây là mã trong sân chơi - https://play.golang.org/p/HmFfM6Grqh


Go có một hàm Round, bạn có thể sử dụng để làm tròn đến số nguyên gần nhất: math.Round (-64,99) sẽ xuất ra -65.
AHonarmand

2

Bạn có thể sử dụng int()hàm để chuyển đổi float64dữ liệu kiểu thành một int. Tương tự bạn có thể sử dụngfloat64()

Thí dụ:

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

Có thể mong muốn làm tròn chính xác.

Do đó, math.Round () là người bạn nhanh chóng (!) Của bạn. Các phương pháp tiếp cận với fmt.Sprintf và strconv.Atois () chậm hơn 2 bậc về cường độ theo các thử nghiệm của tôi với ma trận các giá trị float64 nhằm trở thành các giá trị int được làm tròn chính xác.

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 () trả về một giá trị float64 nhưng với int () được áp dụng sau đó, tôi không thể tìm thấy bất kỳ sự không khớp nào cho đến nay.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.