讲解
Python 的数字主要有两种类型:int(整数)和 float(浮点数)。int 有个让很多语言羡慕的特性:精度无上限,2 的 1000 次方照样算得精确,不存在 JavaScript 那种「安全整数上限」问题。float 是 64 位双精度浮点数(IEEE 754),因此小数运算有精度误差:0.1 + 0.2 得到 0.30000000000000004 而不是 0.3——这不是 Python 的 bug,是所有使用 IEEE 754 的语言的共性。
除法规则要特别留意:/ 永远是「真除法」,10 / 5 得到 2.0 而不是 2;要整数除法用 //(向下取整),求余数用 %,乘方用 **。// 对负数是向下取整:-7 // 2 得 -4 而不是 -3;相应地 -7 % 3 得 2(余数符号跟随除数),这和某些语言不同。另外还有 divmod(a, b) 一次返回商和余数,以及 abs() 取绝对值、round() 四舍五入——但 round 是「银行家舍入」,round(2.5) 得 2,别指望它是 .5 进位。
处理金额等需要精确小数的场景,标准库提供了 decimal 模块的 Decimal 类型,用字符串构造即可避免二进制误差;分数计算有 fractions 模块。日常格式化小数展示用 f-string 的格式说明最方便:f'{3.14159:.2f}' 得到 '3.14'。整数还可以用不同进制书写:0b 二进制、0o 八进制、0x 十六进制,bin()、oct()、hex() 做反向转换。
示例
# 整数精度无上限
print('2 的 100 次方:', 2 ** 100)
# 浮点精度误差:IEEE 754 的共性
print('0.1 + 0.2 =', 0.1 + 0.2)
print('等于 0.3 吗:', 0.1 + 0.2 == 0.3)
# 除法家族:/ 真除法,// 向下取整,% 取余
print('10 / 5 =', 10 / 5, type(10 / 5))
print('7 // 2 =', 7 // 2, ', 7 % 2 =', 7 % 2)
print('-7 // 2 =', -7 // 2, ', -7 % 2 =', -7 % 2)
print('divmod(7, 2) =', divmod(7, 2))
# round 是银行家舍入
print('round(2.5) =', round(2.5), ',round(3.5) =', round(3.5))
# 精确小数:金额场景用 Decimal
from decimal import Decimal
price = Decimal('0.1') + Decimal('0.2')
print('Decimal 精确计算:', price)
# 进制
print('0b1010 =', 0b1010, ',hex(255) =', hex(255))
# 格式化展示
print(f'圆周率保留两位:{3.14159:.2f}')
print(f'一千逗号分隔:{1000000:,}')
常见坑
- 用 == 判断浮点计算结果:0.1 + 0.2 == 0.3 是 False。判断浮点「足够接近」用 math.isclose(a, b) 或比较差值是否小于一个很小数。
- 以为 / 会取整:从 Python 2 过来的习惯是 7 / 2 得 3,Python 3 里 / 永远返回 float,取整请用 //。
- 把 round 当四舍五入:round(2.5) 是 2(银行家舍入,逢 5 向偶数靠)。要严格四舍五入用 Decimal 的 quantize。
- 给金额用 float:0.1 无法被二进制精确表示,累加会积少成多。财务场景一律 Decimal,并用字符串构造。
小结
int 精度无限、float 有 IEEE 754 误差;/ 真除法、// 向下取整、** 乘方;精确小数用 Decimal,格式化用 f-string。下一节看文本:字符串。