为何Go与Python执行大数除法时返回结果不同?
为何Go与Python在执行大数除法时返回结果不同?
代码与输出对比
Go语言实现
package main import ( "fmt" "math/big" ) func main() { x, y := big.NewFloat(26959535291011309493156476344723991336010898738574164086137773096960), big.NewFloat(14484.162361) z := new(big.Float).Quo(x, y) fmt.Println(fmt.Sprintf("%f", z)) }
输出:
1861311315012765262390495455137379355146730679910059382988079104.000000
Python实现
v1 = 26959535291011309493156476344723991336010898738574164086137773096960000000 v2 = 14484162361 print(v1 / v2)
输出:
1861311315012765306929610463010191006516769515973403833769533170
核心差异原因
两者结果不同的本质是计算时的精度模型和数值表示方式完全不同:
1. Go的big.Float存在精度损耗
- 你用
big.NewFloat(14484.162361)初始化除数时,这个十进制小数首先会被转成float64类型存储。但float64是双精度浮点数,无法精确表示所有十进制小数——14484.162361的二进制是无限循环的,只能被近似存储,这就引入了初始误差。 - 后续的除法运算中,
big.Float默认继承了float64的64位精度,这个微小的初始误差会随着超大数运算被不断放大,最终导致结果和精确值出现明显偏差。
2. Python的任意精度整数运算无损耗
- 你在Python中使用的
v1和v2都是任意精度整数,Python对整数的大小没有限制,能精确存储和计算这些超大数值。 - 虽然你用了
/运算符,但因为v1恰好是v2的整数倍,Python内部会直接返回精确的整数结果(如果结果不是整数,/会返回精度有限的float,但这个场景下不存在这个问题)。
让Go得到精确结果的解决方案
要在Go中得到和Python一致的精确结果,建议改用整数运算完全规避浮点数的精度问题:
package main import ( "fmt" "math/big" ) func main() { // 用字符串初始化超大整数,避免float64的精度损失 x := new(big.Int) x.SetString("26959535291011309493156476344723991336010898738574164086137773096960", 10) // 将原除法转为整数运算:x/14484.162361 = (x*100000000)/14484162361 x.Mul(x, big.NewInt(100000000)) y := big.NewInt(14484162361) z := new(big.Int).Div(x, y) fmt.Println(z) }
这段代码会输出和Python完全一致的精确结果,因为全程使用整数运算,没有任何近似误差。
内容的提问来源于stack exchange,提问作者user3675730
相关产品推荐
相关产品推荐

