Как правильно конвертировать 999999999.99999999 в целое число - PullRequest
0 голосов
/ 06 апреля 2020

У меня есть число с плавающей запятой 999999999.99999999, и я хочу преобразовать число с плавающей точкой в ​​целое число. Я ожидаю результата 99999999999999999, но получил 100000000000000000 Почему?)

import (
    "github.com/shopspring/decimal"
    "log"
)

func MultiplyFloatToInt(value float64, multiplier int64) (result int64) {
    return decimal.NewFromFloat(value).Mul(decimal.NewFromFloat(float64(multiplier))).IntPart()
}

func main() {
    bigFloat := float64(999999999.99999999)

    multilayer := float64(100000000)

    log.Println(bigFloat)
    log.Println(int64(bigFloat * multilayer))
    log.Println(MultiplyFloatToInt(bigFloat, int64(multilayer)))
}

https://play.golang.org/p/_1rmUkjf9Nr

Ответы [ 2 ]

3 голосов
/ 06 апреля 2020

Ваше название и тело вопроса противоречат приведенному вами коду. Но проблема заключается в том, как вы создаете bigFloat.

999999999.99999999 - это константа double, но нет double, который мог бы смоделировать это точное значение, поэтому наиболее близкое к нему выбран, и это 100000000. Неважно, что он передается в качестве аргумента конструктору объекта, способного представить ваше исходное число: к тому времени обращение к ближайшему double уже произошло.

Нормальная вещь, которую нужно сделать здесь используется конструктор, который принимает строку.

1 голос
/ 06 апреля 2020

Преобразование любого числа с плавающей точкой в ​​целое число всегда приводит к целому числу. Я не уверен, ожидали ли вы десятичного вывода или неправильно набрали свой вопрос.

Причина, по которой ваш пример округляется вверх, была объяснена в других ответах и ​​комментариях и связана с вашим вводом, превышающим точность float64. Если вы удалите одну из девяток из вашего примера и воспроизведете ее, вы увидите, что значение не округляется в большую сторону.

При работе с числами, выходящими за пределы float64, вы можете использовать библиотеку math / big .

Нечто подобное должно дать ожидаемый результат.

package main

import (
    "math/big"
    "log"
)

func main() {
    bigFloatStr := "999999999.99999999"
    bigFloat, _ := new(big.Float).SetString(bigFloatStr)

    multiplier := new(big.Float).SetInt64(100000000)

    result := new(big.Float)
    result.Mul(bigFloat, multiplier)

    bigInt := new(big.Int)
    result.Int(bigInt)

    intVal := bigInt.Int64()

    log.Println(bigFloat)
    log.Println(result)
    log.Println(bigInt)
    log.Println(intVal) 
}

Вывод:

2009/11/10 23:00:00 9.9999999999999999e+08
2009/11/10 23:00:00 9.9999999999999999e+16
2009/11/10 23:00:00 99999999999999999
2009/11/10 23:00:00 99999999999999999

https://play.golang.org/p/w4fMuPE1ADf

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...