1. 为什么Python的round函数会"骗人"?
第一次用Python做财务计算时,我差点被round函数坑惨了。当时需要计算季度利息,用round(2.735, 2)期待得到2.74,结果却返回了2.73。这种反直觉的结果在金融、科学计算等场景简直是灾难。后来才发现,Python的round函数采用的是银行家舍入法(又称四舍六入五成双),和我们从小学习的"四舍五入"完全不同。
银行家舍入法的规则很有意思:
- 当舍去位小于5时直接舍去
- 当舍去位大于5时进位
- 当舍去位等于5时,看前一位数字:奇数则进位,偶数则舍去
举个例子:
python复制print(round(2.735, 2)) # 输出2.73(5前面是3,奇数所以进位)
print(round(2.725, 2)) # 输出2.72(5前面是2,偶数所以舍去)
print(round(2.736, 2)) # 输出2.74(6大于5直接进位)
这种设计其实很有数学智慧——长期统计下来,舍入误差会更小。但对需要严格四舍五入的场景,这就是个坑。更坑的是浮点数的二进制表示问题,比如:
python复制print(round(2.675, 2)) # 你以为会输出2.68,实际输出2.67
因为2.675在计算机中实际存储的是2.6749999999999998,所以按照规则舍去了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 字符串格式化的取巧方案
当发现round不靠谱后,我第一个想到的是用字符串格式化。f-string和format方法确实能实现视觉上的四舍五入:
python复制print(f"{2.735:.2f}") # 输出2.74
print(f"{2.725:.2f}") # 输出2.73
看起来完美解决了问题?别高兴太早。这种方法有两个致命缺陷:
- 返回的是字符串类型,后续计算需要再转回浮点数
- 本质上还是基于浮点数运算,精度问题依然存在
比如这个例子:
python复制num = 3.145
print(f"{num:.2f}") # 输出3.15(看似正确)
print(float(f"{num:.2f}")) # 转回浮点数后实际值是3.1499999999999999
字符串格式化适合最终展示,但不适合
