แปลง float64 เป็น int ใน Go


125

วิธีการแปลง float64 เป็น int ใน Go? ฉันรู้ว่าstrconvแพคเกจสามารถใช้เพื่อแปลงอะไรก็ได้เป็นหรือจากสตริง แต่ไม่สามารถใช้ระหว่างประเภทข้อมูลที่หนึ่งไม่ใช่สตริง ฉันรู้ว่าฉันสามารถใช้fmt.Sprintfเพื่อแปลงอะไรก็ได้เป็นสตริงจากนั้นstrconvให้เป็นประเภทข้อมูลที่ฉันต้องการ แต่การแปลงเพิ่มเติมนี้ดูงุ่มง่ามเล็กน้อย - มีวิธีที่ดีกว่านี้ไหมในการทำเช่นนี้


int(Round(f))เพื่อตั้งค่า float64 เป็น int ดูstackoverflow.com/a/62753031/12817546 float64(i)เพื่อตั้งค่า int เป็น float64 ดูstackoverflow.com/a/62737936/12817546
Tom J

คำตอบ:


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 การแปลงนี้เหมือนกับ Math.Floor (x) หรือไม่หรือว่ามันลดลง. 7 เพราะวิธีที่ float64 บันทึกไว้ในหน่วยความจำ?
David Larsen

3
@DavidLarsen จากข้อกำหนด Go: "เมื่อแปลงตัวเลขทศนิยมเป็นจำนวนเต็มเศษส่วนจะถูกทิ้ง (ตัดทอนเป็นศูนย์)" ( Go spec )
kvu787

3
การแคสต์ดังกล่าวมีปัญหาใน Go ที่อาจคาดไม่ถึง (อย่างน้อยถ้าคุณมาจาก Java): "ในการแปลงที่ไม่ใช่ค่าคงที่ทั้งหมดที่เกี่ยวข้องกับทศนิยมหรือค่าเชิงซ้อนหากประเภทผลลัพธ์ไม่สามารถแสดงมูลค่าที่การแปลงสำเร็จ แต่ผลลัพธ์ ค่าขึ้นอยู่กับการนำไปใช้งาน " ( golang.org/ref/spec#Conversions ) ดังนั้นหากคุณใช้ค่าที่มีขนาดใหญ่มากอย่างมีประสิทธิภาพเป็นอินฟินิตี้และคุณแปลงเป็น int ผลลัพธ์จะไม่ได้กำหนดไว้ (ไม่เหมือนกับ Java ซึ่งเป็นค่าสูงสุดของประเภทจำนวนเต็ม)
Jaan

12

เพียงแค่แคสต์ไปที่ int จะตัดการลอยตัวซึ่งหากระบบของคุณแสดง 2.0 ภายในเป็น 1.9999999999 คุณจะไม่ได้รับสิ่งที่คุณคาดหวัง การแปลง printf ต่างๆจัดการกับสิ่งนี้และปัดเศษตัวเลขอย่างเหมาะสมเมื่อทำการแปลง ดังนั้นเพื่อให้ได้มูลค่าที่แม่นยำยิ่งขึ้นการแปลงจึงซับซ้อนกว่าที่คุณคาดไว้ในตอนแรก:

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


8

ถ้าแค่จาก float64 ถึง int ก็น่าจะใช้ได้

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

ขาออก:

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

นี่คือรหัสในสนามเด็กเล่น - https://play.golang.org/p/HmFfM6Grqh


Go มีฟังก์ชัน Round ที่คุณสามารถใช้รอบนั้นเป็นจำนวนเต็มใกล้เคียงที่สุด: คณิตศาสตร์ Round (-64.99) จะแสดงผล -65
AHonarmand

2

คุณสามารถใช้int()ฟังก์ชันเพื่อแปลงfloat64ข้อมูลประเภทเป็นintไฟล์. ในทำนองเดียวกันคุณสามารถใช้float64()

ตัวอย่าง:

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

การปัดเศษที่ถูกต้องเป็นไปได้ว่าต้องการ

ดังนั้นคณิตศาสตร์ Round () คือเพื่อน (!) ที่รวดเร็วของคุณ แนวทางด้วย fmt.Sprintf และ strconv.Atois () มีขนาดช้าลง 2 ลำดับตามการทดสอบของฉันด้วยเมทริกซ์ของค่า float64 ที่ตั้งใจให้เป็นค่า 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 () ส่งคืนค่า float64 แต่เมื่อใช้ int () หลังจากนั้นฉันไม่พบข้อผิดพลาดใด ๆ เลย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.