golang转换big.Float到big.Int

时间:2017-11-29 05:47:16

标签: go

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

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

2 个答案:

答案 0 :(得分:3)

大于uint64的大型int将始终导致溢出,因为uint64具有固定大小。您应该在*Float上使用以下method

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

答案 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