You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Go的big.Float类型精度反而低于float64?附代码示例

为什么Go语言中使用big.Float反而精度不如float64?

同样的Nilakantha级数计算π的逻辑,用float64得到的结果符合预期,但用更高精度的big.Float却得到了严重偏离的结果,这是为什么?明明代码逻辑看起来完全一致,按道理big.Float应该给出更精确的结果才对。

// 以下代码行为不符合预期,原因是什么?
// π = 3 + 4/(2*3*4) - 4/(4*5*6) + 4/(6*7*8) - 4/(8*9*10) + 4/(10*11*12) ...

package main

import (
    "fmt" 
    "math/big" 
)

func main(){
    with_float64_types()
    with_big_Float_types() 
}

// 使用float64类型的实现
func with_float64_types() {

// float64常量:
        var four64 float64    
            four64 = 4

        var three64 float64
            three64 = 3 

// float64变量:
        var digitone64 float64
            digitone64 = 2

        var digittwo64 float64
            digittwo64 = 3

        var digitthree64 float64
            digitthree64 = 4

        var sum64 float64    
            sum64 = three64 + (four64 / (digitone64*digittwo64*digitthree64)) 

        var nextterm64 float64

// float64计算过程:
        iters_fl64 := 1
    for iters_fl64 < 100000 { // 循环100,000次
        iters_fl64++
        digitone64 = digitone64 + 2 
        digittwo64 = digittwo64 + 2
        digitthree64 = digitthree64 + 2 
        nextterm64 = four64/(digitone64*digittwo64*digitthree64)
            if iters_fl64 % 2 == 0 {  // %是取模运算符
                sum64 = sum64 - nextterm64 
            } else {
                sum64 = sum64 + nextterm64
            }
    }
    fmt.Printf("\n用float64计算的Nilakantha圆周率:%0.22f \n", sum64)
    // 输出 3.1415926535897864546598,结果符合预期
}

// 使用big.Float类型的实现
func with_big_Float_types() {

// big.Float常量:
        twoBig := big.NewFloat(2)
        threeBig := big.NewFloat(3)
        fourBig := big.NewFloat(4)

// big.Float变量:
        digitoneBig := new(big.Float)        
        digitoneBig = twoBig 
        digittwoBig := new(big.Float)
        digittwoBig = threeBig 
        digitthreeBig := new(big.Float)
        digitthreeBig = fourBig

        sumBig := new(big.Float) 
        nexttermBig := new(big.Float) 

    precision := 512
        sumBig.SetPrec(uint(precision))
        twoBig.SetPrec(uint(precision))
        threeBig.SetPrec(uint(precision))
        fourBig.SetPrec(uint(precision))
        digitoneBig.SetPrec(uint(precision))       
        digittwoBig.SetPrec(uint(precision))
        digitthreeBig.SetPrec(uint(precision))
        nexttermBig.SetPrec(uint(precision))

        sumBig.Add(threeBig, (new(big.Float).Quo(fourBig, new(big.Float).Mul(digitoneBig, new(big.Float).Mul(digittwoBig, digitthreeBig)))))

// big.Float计算过程:
                iterBig := 1
            for iterBig < 100000 { // 循环100,000次
                iterBig++

                digitoneBig.Add(digitoneBig, twoBig)
                digittwoBig.Add(digittwoBig, twoBig)
                digitthreeBig.Add(digitthreeBig, twoBig)

                nexttermBig.Quo(fourBig, new(big.Float).Mul(digitoneBig, new(big.Float).Mul(digittwoBig, digitthreeBig)))

                    if iterBig % 2 == 0 {  // %是取模运算符
                        sumBig.Sub(sumBig, nexttermBig) 
                    } else {
                        sumBig.Add(sumBig, nexttermBig)
                    }
            }
    fmt.Printf("\n用big.Float计算的Nilakantha圆周率:%0.22f \n", sumBig)
    // 输出 3.1376671059697782695252,结果严重偏离预期,但为什么?逻辑不是完全一致吗?
}

问题根源

问题出在big.Float的变量赋值方式上:Go语言中big.Float是引用类型,直接用=赋值只是复制指针,让新变量指向同一个底层对象。

看这段错误的初始化代码:

digitoneBig := new(big.Float)        
digitoneBig = twoBig 

这里digitoneBig并没有创建独立的big.Float实例,而是直接指向了twoBig的内存地址。后续循环中执行digitoneBig.Add(digitoneBig, twoBig)时,实际上是修改了twoBig本身的值!

第一次循环:digitoneBig(也就是twoBig)从2变成2+2=4;第二次循环时,twoBig已经是4了,所以digitoneBig.Add会变成4+4=8,以此类推——每次加的不再是固定的2,而是越来越大的数,导致整个Nilakantha级数的项完全错误,结果自然严重偏离π的真实值。

而float64是值类型,赋值时会拷贝值,所以不会出现这种引用共享的问题。

修正方案

要正确初始化big.Float变量,需要使用Set方法复制值,确保每个变量拥有独立的实例:

// 修正后的big.Float变量初始化部分
digitoneBig := new(big.Float).Set(twoBig)
digittwoBig := new(big.Float).Set(threeBig)
digitthreeBig := new(big.Float).Set(fourBig)

这样后续的Add操作只会修改各自的变量,不会影响到twoBig等常量,循环中每次加的都是固定的2,就能得到正确的高精度结果。

内容的提问来源于stack exchange,提问作者user2421775

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:37:30