python整数不会溢出但float会静默失准:int为任意精度,float基于ieee 754双精度,超253后无法精确表示整数,导致1016+1==10**16为true、0.1+0.2!=0.3等错误。

Python 整数不会溢出,但 float 会 silently 失准
Python 的 int 类型是任意精度的,加到内存耗尽前都不会“溢出”,但这是假安全感——真正踩坑的是 float。它底层用 IEEE 754 双精度表示,超过 2**53 后就无法精确表示每个整数,后续运算开始丢位。
常见错误现象:10**16 + 1 == 10**16 返回 True;用 float 做金融计算时出现 0.1 + 0.2 != 0.3;科学计算中迭代误差滚雪球。
- 使用场景:读取 CSV 数值列(默认转
float)、调用 C 扩展返回double、与 NumPy 交互(np.float64同构) - 关键参数差异:
sys.float_info.dig是十进制有效位数(通常 15),sys.float_info.max是最大可表示值(约1.8e308),但“最大”不等于“精确” - 性能影响:换成
decimal.Decimal或fractions.Fraction会慢 10–100 倍,别在热循环里用
NumPy 的 int64 / float64 溢出行为完全不同
NumPy 数组用固定宽度类型,int64 加法超限会 wraparound(如 2**63-1 + 1 变成 -2**63),float64 超限则变 inf 或 nan,且不报错。
常见错误现象:np.array([2**63-1], dtype=np.int64) + 1 得到负数;np.log(0) 返回 -inf,后续 np.sqrt(-inf) 得 nan,再参与求和就污染整个结果。
立即学习“Python免费学习笔记(深入)”;
- 使用场景:处理图像像素(
uint8)、时间戳(int64微秒)、机器学习特征缩放 - 检测方法:启用
np.seterr(all='raise')捕获FloatingPointError;对整数数组用np.iinfo(np.int64).max做前置校验 - 兼容性注意:Pandas 默认用
float64存整数列(含NaN),读大数 CSV 时可能意外降精度,显式指定dtype={'col': 'Int64'}(大写 I)启用 nullable integer
如何判断当前数值是否已失真
不能只看是否报错——大多数溢出或精度丢失是静默发生的。得主动验证。
- 对 float:用
math.isfinite(x)排除inf/nan;用x == x + 0检查是否还能加 0(inf不满足);更严格用abs(x - round(x)) > 1e-10看是否本该是整数却漂移了 - 对整数运算链:用
decimal.Decimal重跑关键路径做交叉比对,例如Decimal('1.1') + Decimal('2.2')对比1.1 + 2.2 - 路径依赖:如果输入来自
struct.unpack('d', ...)或ctypes.c_double,直接视为不可信 float,优先转Decimal再算
真实项目里最该盯住的三个点
不是所有数值都值得较真,但以下三处一旦出错,debug 成本极高。
- 数据库 roundtrip:PostgreSQL 的
NUMERIC或 MySQL 的DECIMAL读到 Python 变成float,再写回去就丢精度。用 SQLAlchemy 时设type_=Numeric(precision=12, scale=2)并配decimal_return_scale=2 - JSON 序列化:
json.dumps({'x': 1e20})输出字符串"1e+20",但反序列化后是float,再算int()就可能截断。需要自定义json.JSONEncoder把大数转字符串,或用decimal解析 - 时间戳计算:
time.time() * 1000是常见写法,但超过2**53毫秒(约 285 年后)就会丢毫秒精度。用time.time_ns()(Python 3.7+)替代
复杂点在于,很多溢出不发生在你写的那行代码,而是在你依赖的库内部——比如某个 requests 响应头里带的时间戳被自动转成了 float。得习惯在关键数据流入口打日志,输出 repr(x) 而不是 str(x)。










