简体   繁体   English

golang 将 big.Float 转换为 big.Int

[英]golang convert big.Float to big.Int

convert big.Float to big.Int, i write code below, but it overflow with uint64, so what's the correct way to cenvert big.Float to big.Int.将 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)))
}

A big int bigger than uint64 will always cause an overflow as uint64 has fixed size.由于uint64具有固定大小, uint64大于uint64 big int 将始终导致溢出。 You should use the following method on *Float :您应该在*Float上使用以下方法

func (*Float) Int

The changes required would be:所需的更改是:

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
}

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

使用函数Float.Int(nil)

I have worked with a regular float64 number (not big.Float) and found out that conversion via string is the most precise way.我使用了一个普通的 float64 数字(不是 big.Float),发现通过字符串进行转换是最精确的方法。 Check it out一探究竟

Note: the example is for float64 -> decimal(,20) conversion.注意:该示例用于 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 https://play.golang.org/p/_lkyQ_0udjd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM