大家好,我是正在实战各种 AI 项目的程序员晚枫。
Python 的 int 可以无限大,float 是双精度,它们在 C 中如何实现?这一讲,揭开数字类型的底层秘密。
📖 开篇:为什么 Python 的 int 没有上限?
在 C 语言里,int 是有限制的:
1 | int i = 2147483647; |
但在 Python 里:
1 | i = 2147483647 |
秘密在于:Python 的整数不是 C 的 int,而是变长数组!
🔢 PyLongObject(整数)
1 | // Include/longintrepr.h |
数字如何存储?
Python 用「30位进制」存储大整数。每个 digit 占 30 位(某些平台是 15 位):
1 | # 假设存储数字 2^60 = 1152921504606846976 |
这就解释了为什么 2**60 和 2**30 * 2**30 速度不同——大整数的位数越多,运算越慢。
🧠 小整数缓存
Python 在启动时预创建了 -5 到 256 的整数对象:
1 | // Objects/longobject.c |
验证一下:
1 | a = 256 |
性能提示:判断整数是否相等用
==,判断是否是同一对象用is。不要用is比较普通整数大小!
💧 PyFloatObject(浮点数)
1 | // Include/floatobject.h |
浮点数使用标准的 IEEE 754 双精度格式:
- 1 位符号
- 11 位指数
- 52 位尾数
1 | import sys |
精度陷阱
1 | # 经典问题 |
🔧 整数运算的底层实现
加法
1 | // Objects/longobject.c |
乘法(Karatsuba 算法)
Python 3 的乘法使用 Karatsuba 分治算法,时间复杂度从 O(n²) 降到 O(n^1.585):
1 | # 两个大整数相乘的字节码 |
位运算
1 | x = 1 << 1000 # 2 的 1000 次方,毫无压力! |
📊 为什么小整数比大整数快?
1 | import time |
原因:
- 小整数在缓存中,不需要分配内存
- 小整数的 digit 数组长度 = 1,不需要进位处理
- 大整数的位数越多,乘法复杂度越高
💡 本节作业
- 用
sys.getsizeof()比较不同大小整数的内存占用 - 验证
is比较在小整数(100)和大整数(1000)上的差异 - 思考:为什么
2**100比2**10 * 2**10快?
🎯 本讲总结
PyLongObject:变长数组存储大整数,每段 30 位。
小整数缓存:-5 到 256 的整数被预创建,is 比较返回 True。
PyFloatObject:IEEE 754 双精度,精度陷阱需用 decimal 处理。
性能真相:小整数运算快是因为有缓存且位数少。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
🔗 课程导航
← 上一讲:常见字节码指令 | 下一讲:字符串类型实现 →
💬 联系我
| 平台 | 账号/链接 |
|---|---|
| 微信 | 扫码加好友 |
| B 站 | Python 自动化办公社区 |
主营业务:AI 编程培训、企业内训、技术咨询