Перетворити float64 в int в Go


124

Як можна перетворити 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 .
Том J

Відповіді:


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, Тож це перетворення те саме, що і Math.Floor (x), або він кидає .7 через те, як float64 зберігає його в пам'яті?
Девід Ларсен

3
@DavidLarsen Із специфікації Go: "При перетворенні числа з плаваючою комою в ціле число дробу відкидають (усічення до нуля)". ( Go spec )
kvu787

3
Такі касти мають проблему в Go, яка може бути несподіваною (принаймні, якщо ви приїжджаєте з Java): "У всіх нестабільних перетвореннях, що включають значення з плаваючою комою або складні значення, якщо тип результату не може представляти значення, яке конверсія вдається, але результат значення залежить від реалізації. " ( golang.org/ref/spec#Conversions ). Отже, якщо ви використовуєте дуже велике значення ефективно як нескінченність, і перетворюєте його в int, результат не визначений (на відміну від Java, де це максимальне значення цілого числа).
Яан

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


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, яку ви можете використати для округлення до найближчого цілого числа: math.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

Вірогідне бажане правильне округлення.

Тому math.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 () згодом я не міг знайти жодних невідповідностей.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.