math/big 是任意精度整数/浮点数的可控计算工具,不重载运算符、无自动内存管理、不默认线程安全;big.Int 方法原地修改接收者,需显式拷贝、判 ok、复用变量或 sync.Pool 优化。

直接说结论:math/big 不是“高精度浮点库”,而是**任意精度整数/浮点数的可控计算工具**;它不重载运算符、不自动内存管理、不默认线程安全——用错一个参数或忽略一个返回值,结果就可能静默错误或 panic。
为什么 big.Int.Add(a, b) 会改掉 a?
big.Int 是值类型但设计为可变(mutable),所有算术方法(Add、Mul、Sub、Div)都原地修改接收者。写成 a.Add(a, b) 就是让 a 变成 a + b 的结果,不是“返回新值”。
- 常见错误:以为
c := a.Add(b, c)是把b + c赋给c,其实a已被覆盖,且c类型不匹配(Add接收者必须是第一个参数) - 正确写法:先声明目标变量,再链式调用 ——
res := new(big.Int).Add(a, b).Mul(res, c) - 要保留原值?必须显式拷贝:
copy := new(big.Int).Set(a);big.Int没有Clone()方法 - 性能影响:循环中反复
new(big.Int)会触发 GC;高频场景建议复用局部变量或用sync.Pool管理
字符串转 big.Int 为什么有时返回 nil 却没报错?
SetString() 解析失败时返回 (nil, false),不 panic、不打印日志——只靠第二个 ok 布尔值判断。很多代码漏检 ok,导致后续操作 panic。
- 典型静默失败原因:
"0x1a2b"(含前缀)、" 123 "(首尾空格)、"- 456"(负号后带空格)、"123.45"(含小数点) - 十六进制必须显式传
16:i.SetString("1a2b", 16);"0x1a2b"要先strings.TrimPrefix(s, "0x") - 安全做法:解析前
strings.TrimSpace(),解析后必判ok,别信 “字符串看着没问题” - 别绕路:
strconv.ParseInt或fmt.Sscanf无法处理超int64的字面量,纯属徒劳
Exp(x, y, m) 就是 Go 的 pow(),但 m 参数容易误解
(*big.Int).Exp 是唯一原生幂运算方法,支持普通幂和模幂,但语义和 Python 的 pow(a, n, m) 不完全一致——关键在 m 的行为。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
立即学习“go语言免费学习笔记(深入)”;
-
m == nil或m.Sign() == 0(即m是零值)→ 执行x^y,不是报错 -
m != nil→ 自动取|m|(绝对值),m符号被忽略,无需手动abs(m) - 指数
y必须非负;y 时结果恒为 <code>1 mod |m|(若m != nil),或1(若m == nil) - 底数
x可为负,但模幂结果始终是非负整数(在[0, |m|-1]区间) - 别传
nil的x或y:方法不校验,直接 panic
big.Float 精度不是“保留几位小数”,而是二进制位数
big.Float 的 SetPrec(n) 设置的是**二进制有效位数**,不是十进制小数位。设成 10 并不等于保留 10 位小数,而是约等于 3 位十进制有效数字(因 log₁₀(2¹⁰) ≈ 3.01)。
- 常见错觉:设了
SetPrec(100),再用Text('g', 20)输出,结果却只有十几位——因为内部精度不够,格式化补再多也没用 - 模拟
float64级别精度?用SetPrec(53);需要更高,请按需上调(如256) -
Text('g', d)的d是**最大有效数字位数**,不是小数位数;要固定小数位,得自己做四舍五入逻辑 - 比较两个
big.Float是否相等?不能用==,必须用Cmp();Float64()会立刻降级为float64精度,慎用
最易被忽略的一点:所有 math/big 类型都不是并发安全的。多个 goroutine 同时对同一个 *big.Int 调 Add 或 Set,会数据竞争甚至 panic——没有例外,也不靠文档提醒,全靠你主动加锁或隔离实例。

















