Golang如何将big.Float转换为big.Int

8

将big.Float转换为big.Int,我编写了以下代码,但它会在uint64上溢出,那么正确的方法是什么呢?

package main

import "fmt"
import "math/big"

func FloatToBigInt(val float64) *big.Int {
    bigval := new(big.Float)
    bigval.SetFloat64(val)

    coin := new(big.Float)
    coin.SetInt(big.NewInt(1000000000000000000))
    bigval.Mul(bigval, coin)

    result := new(big.Int)
    f,_ := bigval.Uint64()
    result.SetUint64(f)

    return result
}

func main() {
    fmt.Println("vim-go")
    fmt.Println(FloatToBigInt(float64(10)))
    fmt.Println(FloatToBigInt(float64(20)))
    fmt.Println(FloatToBigInt(float64(30)))
    fmt.Println(FloatToBigInt(float64(40)))
    fmt.Println(FloatToBigInt(float64(50)))
    fmt.Println(FloatToBigInt(float64(100)))
    fmt.Println(FloatToBigInt(float64(1000)))
    fmt.Println(FloatToBigInt(float64(10000)))
}
3个回答

10

大于 uint64 的大整数总是会导致溢出,因为 uint64 有固定的大小。您应该在 *Float 上使用以下方法

func (*Float) Int

需要进行的修改如下:

func FloatToBigInt(val float64) *big.Int {
    bigval := new(big.Float)
    bigval.SetFloat64(val)
    // Set precision if required.
    // bigval.SetPrec(64)

    coin := new(big.Float)
    coin.SetInt(big.NewInt(1000000000000000000))

    bigval.Mul(bigval, coin)

    result := new(big.Int)
    bigval.Int(result) // store converted number in result

    return result
}

工作示例:https://play.golang.org/p/sEhH6iPkrK


谢谢,它运行正常。但是您看这个例子https://play.golang.org/p/P02AN1e09C也有一些问题。 - goask
bigval 的默认精度为 53 位。您需要将此值增加以获得准确的结果:https://play.golang.org/p/Xy88JX57JE。您需要阅读有关浮点精度文档,以确定程序需要的位数。 - abhink

1

0

我曾经使用过普通的float64数字(而不是big.Float),发现通过字符串转换是最精确的方法。试一试吧。

注意:这个例子是将float64转换为decimal(,20)。

func bigIntViaString(flt float64) (b *big.Int) {

    if math.IsNaN(flt) || math.IsInf(flt, 0) {
        return nil // illegal case
    }

    var in = strconv.FormatFloat(flt, 'f', -1, 64)

    const parts = 2

    var ss = strings.SplitN(in, ".", parts)

    // protect from numbers without period
    if len(ss) != parts {
        ss = append(ss, "0")
    }

    // protect from ".0" and "0." values
    if ss[0] == "" {
        ss[0] = "0"
    }

    if ss[1] == "" {
        ss[1] = "0"
    }

    const (
        base     = 10
        fraction = 20
    )

    // get fraction length
    var fract = len(ss[1])
    if fract > fraction {
        ss[1], fract = ss[1][:fraction], fraction
    }

    in = strings.Join([]string{ss[0], ss[1]}, "")
    // convert to big integer from the string
    b, _ = big.NewInt(0).SetString(in, base)
    if fract == fraction {
        return // ready
    }
    // fract < 20, * (20 - fract)
    var (
        ten = big.NewInt(base)
        exp = ten.Exp(ten, big.NewInt(fraction-int64(fract)), nil)
    )
    b = b.Mul(b, exp)
    return

}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接