Go big.Int调用Int64()整数溢出负数转正 如何安全与零比较
问题原因
逻辑出错的核心是整数溢出:big.Int支持任意精度整数存储,取值范围远大于Go原生int64的上下限。示例中diff的实际值为-34326934275868031902,已经小于int64可表示的最小值-9223372036854775808,此时调用Int64()会直接截断高位比特,返回错误的截断结果,必然导致比较逻辑失效。
转float32/float64比较同样不可靠:浮点数对超大整数存在精度丢失问题,整数值超过2^53后float64就无法精确表示每一个整数,同样会引发比较错误。
正确实现方式
不需要将big.Int转换为任何原生数值类型,直接使用big.Int内置的Sign()方法即可完成和0的安全比较,该方法不受数值大小、精度影响,返回值规则固定:
- 返回
1:当前值大于0 - 返回
0:当前值等于0 - 返回
-1:当前值小于0
修正后的可运行代码如下:
package main import ( "fmt" "math/big" ) func main() { var amount1 = &big.Int{} var amount2 = &big.Int{} amount1.SetString("465673065724131968098", 10) amount2.SetString("500000000000000000000", 10) diff := big.NewInt(0).Sub(amount1, amount2) fmt.Println(diff) // 输出:-34326934275868031902 // 用Sign()方法安全比较 switch diff.Sign() { case 1: fmt.Println(diff, "is bigger than 0") case 0: fmt.Println(diff, "is equal to 0") case -1: fmt.Println(diff, "is smaller than 0") } }
如果需要比较两个big.Int类型值的大小(而非和0比较),可以使用Cmp()方法,规则和Sign()一致:a.Cmp(b)返回1代表a>b,返回0代表a==b,返回-1代表a<b。
内容的提问来源于stack exchange,提问作者rihekopo
相关产品推荐
相关产品推荐

