Python中round()函数返回错误结果的原因及解决方法
问题原因与解决办法
这其实是浮点数二进制存储的精度问题导致的,很多刚接触Python的开发者都会遇到这个“反直觉”的情况!
为什么会出现这种差异?
计算机中的float类型是用二进制存储的,但很多十进制小数无法被二进制精确表示,会变成无限循环的二进制小数,存储时只能取近似值。举个例子:
- 你看到的
5.45,实际在计算机中存储的是一个略大于5.45的值(比如5.4500000000000001776...) - 而
5674.45实际存储的是一个略小于5674.45的值(比如5674.449999999999317...)
当你调用round()函数时,它是基于这个近似值来计算的:
- 对于略大于5.45的数,保留1位小数时会向上舍入到
5.5 - 对于略小于5674.45的数,保留1位小数时会向下舍入到
5674.4
你可以用repr()函数查看浮点数的真实存储值来验证:
print(repr(5.45)) # 输出 '5.45000000000000017763568394002504646778106689453125' print(repr(5674.45)) # 输出 '5674.449999999999317878973670303821563720703125'
解决办法
最可靠的方式是使用Python标准库中的decimal模块,它可以精确处理十进制数,完全避免浮点数精度问题,并且支持我们熟悉的“四舍五入”规则:
from decimal import Decimal, ROUND_HALF_UP def precise_round(num, decimals): # 将数字转为字符串再转Decimal,避免浮点数转换带来的误差 decimal_num = Decimal(str(num)) # 定义舍入的精度格式,比如1位小数就是'1.0' precision = Decimal('1.' + '0' * decimals) # 使用ROUND_HALF_UP实现标准四舍五入 rounded_decimal = decimal_num.quantize(precision, rounding=ROUND_HALF_UP) # 转回float类型(如果需要的话) return float(rounded_decimal) # 测试你的案例 print(precise_round(5.45, 1)) # 输出 5.5 print(precise_round(5674.45, 1)) # 输出 5674.5 print(precise_round(45357.45, 1)) # 输出 45357.5
如果你不想引入decimal模块,也可以尝试先将数值放大到整数再处理,但要注意这个方法在某些极端场景下仍可能存在精度问题:
def simple_round(num, decimals): factor = 10 ** decimals # 加1e-10是为了修正微小的精度误差,避免因为近似值偏小导致舍入错误 return round(num * factor + 1e-10) / factor print(simple_round(5674.45, 1)) # 输出 5674.5
不过这种方法不如decimal模块稳定,优先推荐前者。
补充说明:Python的round()默认使用的是“银行家舍入法”(四舍六入五成双),但你遇到的问题核心还是浮点数精度导致的实际值偏差,而非舍入规则本身。
内容的提问来源于stack exchange,提问作者shiv_90
相关产品推荐
相关产品推荐

