Перетворити 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.