2. 算术操作数详解:整数、浮点数、复数在算术运算中的表现
聊到 Python 的算术运算,很多人觉得不就是加减乘除嘛,有啥好讲的?
嗯,我刚开始也是这么想的。直到有一次在金融项目里,因为浮点数精度问题导致对账差了 0.01 元,查了整整一个下午。从那以后,我对 Python 的数值类型就再也不敢马虎了。
说白了,整数、浮点数、复数这三种类型,在算术运算中的行为差异很大。不理解这些差异,写出来的代码就可能藏着坑。
2.1 整数:Python 的「大胃王」
Python 的整数和其他语言不太一样。C 语言里 int 有范围限制,超出就溢出。但 Python 的整数是 任意精度 的。
核心特性:Python 3 中 int 可以无限大,只受内存限制。
# 你能想象这么大的整数吗?
big_num = 10 ** 100
print(big_num)
# 输出:10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
# 再大一点也没问题
huge_num = 2 ** 1000
print(len(str(huge_num))) # 302 位数字
我个人习惯在做大数计算时,直接用 Python 的 int,省心。不像 Java 还得用 BigInteger。
小技巧:整数除法用 // 会向下取整。注意是向下,不是向零取整。负数时容易搞错。
print(7 // 3) # 2
print(-7 // 3) # -3,不是 -2!
# 因为 -7/3 ≈ -2.33,向下取整得到 -3
2.2 浮点数:精度是个老话题
浮点数在计算机里是用二进制表示的。你想想看,0.1 在二进制里是个无限循环小数。所以 0.1 + 0.2 不等于 0.3,这是所有语言的通病。
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
我在项目中遇到过最典型的场景:累计金额时,每次加 0.01,加 100 次,结果不是 1.0。财务那边直接炸了。
避坑指南:千万不要用浮点数做精确的金额计算。我曾经吃过这个亏,后来全改成 Decimal 了。
Python 的浮点数遵循 IEEE 754 标准,双精度 64 位。有效数字大约 15-17 位。
| 操作 | 示例 | 结果 | 说明 |
|---|---|---|---|
| 加法 | 0.1 + 0.2 |
0.30000000000000004 | 精度误差 |
| 乘法 | 0.1 * 3 |
0.30000000000000004 | 同样有误差 |
| 比较 | 0.1 + 0.2 == 0.3 |
False | 别直接比较 |
| 取整 | round(2.675, 2) |
2.67 | 银行家舍入 |
建议:比较浮点数时用 math.isclose(),或者自己设个误差范围。
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
# 或者手动设阈值
eps = 1e-9
print(abs(0.1 + 0.2 - 0.3) < eps) # True
2.3 复数:Python 的隐藏技能
说实话,复数在日常开发中用得不多。但做科学计算、信号处理时,它就是主角了。
Python 用 j 表示虚数单位,注意不是 i。
# 定义复数
z1 = 3 + 4j
z2 = 1 - 2j
# 基本运算
print(z1 + z2) # (4+2j)
print(z1 * z2) # (11-2j)
print(z1 / z2) # (-1+2j)
# 获取实部和虚部
print(z1.real) # 3.0
print(z1.imag) # 4.0
我记得有一次做音频频谱分析,用复数表示频域信号,Python 的 cmath 模块帮了大忙。
注意:复数不能直接比较大小。你写 3+4j > 1+2j 会报错。要比较的话,比较模长。
z1 = 3 + 4j
z2 = 1 + 2j
# print(z1 > z2) # TypeError: '>' not supported between instances of 'complex' and 'complex'
# 正确做法:比较模长
print(abs(z1) > abs(z2)) # True
2.4 类型转换:混合运算时的规则
不同类型的数值在一起运算时,Python 会自动做类型提升。规则很简单:朝着更「宽」的类型转换。
宽度顺序:int → float → complex
# int + float → float
print(type(3 + 0.5)) # <class 'float'>
# int + complex → complex
print(type(3 + 4j)) # <class 'complex'>
# float + complex → complex
print(type(3.0 + 4j)) # <class 'complex'>
你想想看,如果 int 和 float 运算结果还是 int,那 3 / 2 就变成 1 了,这显然不合理。Python 3 在这方面做得比 Python 2 好多了。
注意:Python 3 中 / 永远返回浮点数。想要整数结果用 //。
2.5 知识结构图
下面这张图帮你理清三种数值类型在算术运算中的关系:
2.6 实战建议
- 整数运算:放心用,不会溢出。但注意
//的向下取整行为。 - 浮点运算:别做精确比较。用
math.isclose()或设阈值。 - 复数运算:用
cmath模块处理数学函数,别直接比较大小。 - 混合运算:了解类型提升规则,避免意外结果。
个人习惯:我写代码时,只要涉及金额,一律用 Decimal。涉及科学计算,用 numpy 的浮点类型。纯逻辑计数,用 int。各司其职,少踩坑。