Python中round(0.975,2)与round(0.975*100)/100结果差异原因及规避方法
Python中round()函数的浮点数舍入异常解析
问题复现
测试代码
a=0.975 print(round(a,2)) print(round(a*100)/100) a=-0.975 print(round(a,2)) print(round(a*100)/100) a=1.975 print(round(a,2)) print(round(a*100)/100) a=-1.975 print(round(a,2)) print(round(a*100)/100)
输出结果
0.97 0.98 -0.97 -0.98 1.98 1.98 -1.98 -1.98
原因解析
1. 浮点数的二进制存储误差
十进制小数转二进制浮点数时,大部分数值无法精确表示,只能存储为最接近的近似值:
0.975实际存在内存中的值是略小于0.975的0.9749999999999999778;1.975的存储值则是略大于1.975的1.9750000000000001776。
这种误差方向的差异是核心原因,而-1到1区间内的数值更容易出现这类问题,是因为该区间的浮点数尾数精度更高,部分十进制小数的近似值会偏向于略小于原值,超出区间的数值则可能偏向略大于原值。
2. round()的"四舍六入五成双"规则
Python的round()采用银行家舍入规则:当舍入位是5时,会把结果舍入到最近的偶数位。
- 对于存储值略小于0.975的
0.9749999999999999778,它离0.97(百分位为7,奇数)更近,所以round(0.975, 2)返回0.97; - 当执行
0.975*100时,浮点运算的误差积累可能让结果略大于97.5,此时round()会舍入到偶数98,除以100后得到0.98; - 而
1.975的存储值略大于原值,无论直接舍入到两位小数,还是先乘100舍入再除以100,结果都会偏向1.98,所以两次输出一致。
规避方法
1. 用decimal模块做精确运算
decimal模块支持高精度十进制运算,完全避开浮点数存储误差,还能自定义舍入规则:
from decimal import Decimal, ROUND_HALF_UP a = Decimal('0.975') # 四舍五入保留两位小数 print(a.quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)) # 输出0.98 # 先乘100取整再转回两位小数 print((a * Decimal('100')).quantize(Decimal('1')).quantize(Decimal('0.00'))) # 输出0.98
2. 手动添加偏移量修正误差
针对简单场景,可以给数值加一个极小的偏移量,确保舍入方向符合预期:
def round_fix(num, n): # 加1e-10避免浮点数误差导致的舍入偏差 return round(num + 1e-10, n) a = 0.975 print(round_fix(a, 2)) # 输出0.98 print(round_fix(a*100, 0)/100) # 输出0.98
3. 用字符串格式化控制舍入
字符串格式化默认采用四舍五入规则,直接输出符合预期的结果:
a = 0.975 print("{:.2f}".format(a)) # 输出0.98 print("{:.2f}".format(round(a*100)/100)) # 输出0.98
内容的提问来源于stack exchange,提问作者dalleaux
相关产品推荐
相关产品推荐

