dongwen2162 2018-04-04 08:47
浏览 58

除数时,为什么Go和Python返回不同的结果?

// In golang    
x, y := big.NewFloat(26959535291011309493156476344723991336010898738574164086137773096960), big.NewFloat(14484.162361)  
z := new(big.Float).Quo(x, y)
fmt.Println(fmt.Sprintf("%f", z))

output: 1861311315012765262390495455137379355146730679910059382988079104.000000

// In python
v1 = 26959535291011309493156476344723991336010898738574164086137773096960000000
v2= 14484162361
print v1/v2

output:1861311315012765306929610463010191006516769515973403833769533170

  • 写回答

1条回答 默认 最新

  • doushang9172 2018-04-04 08:59
    关注

    You are not doing the same operation in Go and in Python. In Go you divide 2 floating point numbers, while in Python you divide 2 integer numbers. The results are only "roughly" equal because the input numbers you provide lose precision, and the accuracy of the floating point operation is also limited (insufficient).

    If you perform the same integer division in Go (using the big.Int type), you get the same result:

    i, ok := big.NewInt(0).SetString("26959535291011309493156476344723991336010898738574164086137773096960000000", 10)
    if !ok {
        panic("invalid")
    }
    j, ok := big.NewInt(0).SetString("14484162361", 10)
    if !ok {
        panic("invalid")
    }
    
    k := big.NewInt(0).Quo(i, j)
    fmt.Println(k)
    

    This outputs:

    1861311315012765306929610463010191006516769515973403833769533170
    

    If you want to perform floating point division in Go, don't use float64 type to represent your inputs, as they are limited in precision. This will happen because you created your input numbers using big.NewFloat() which has a parameter of float64 type, so the constants you pass will be implicitly converted to float64 and you already lose precision.

    Instead use the big.Float type, and specify your input as string values and set it using Float.SetString(); and manually increase the precision (using Float.SetPrec()). If you do so, you will get the "same" result (same in the integer part, plus some fraction value):

    x, ok := big.NewFloat(0).SetPrec(500).SetString("26959535291011309493156476344723991336010898738574164086137773096960")
    if !ok {
        panic("invalid")
    }
    y, ok := big.NewFloat(0).SetPrec(500).SetString("14484.162361")
    if !ok {
        panic("invalid")
    }
    z := new(big.Float).SetPrec(500).Quo(x, y)
    fmt.Println(fmt.Sprintf("%f", z))
    

    Output:

    1861311315012765306929610463010191006516769515973403833769533170.518151
    

    Try the examples on the Go Playground.

    Note that precision of Float.Quo() depends on:

    Precision, rounding, and accuracy reporting are as for Add.

    Which is:

    If z's precision is 0, it is changed to the larger of x's or y's precision before the operation. Rounding is performed according to z's precision and rounding mode; and z's accuracy reports the result error relative to the exact (not rounded) result.

    评论

报告相同问题?

悬赏问题

  • ¥15 flink cdc无法实时同步mysql数据
  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名