首先需要注意的是,这个问题(意外地向下舍入)只有在您要舍入的数字左侧比其低一位的数字是 5
时有时会出现。
例如:
>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01
但是有一个简单的解决方案,我发现它似乎总是有效的,并且不依赖于导入其他库。解决方案是在你尝试使用round
的数字字符串长度上加上1
的1e-X
。
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*6),2)
0.08
啊哈!所以基于这个,我们可以制作一个方便的包装函数,它是独立的,不需要额外的
import
调用...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1))
基本上,这会添加一个保证比您尝试使用round
的字符串的最小给定数字更小的值。通过添加这个小量,它在大多数情况下保留了round
的行为,同时现在确保如果低于要舍入到的数字的数字是5
,则向上舍入,如果是4
,则向下舍入。
使用10**(-len(val)-1)
的方法是有意为之的,因为它是可以添加以强制移位的最大小数,同时还确保您添加的值即使缺少小数点.
也不会改变舍入。我可以只使用10**(-len(val))
和条件语句if (val>1)
来减去1
,但总体而言,始终减去1
更简单,因为这不会改变此解决方法可以正确处理的十进制数范围。如果您的值达到类型的极限,则此方法将失败,但对于几乎所有有效十进制值的范围,它应该可以正常工作。
你也可以使用decimal库来完成这个任务,但是我提出的包装器更简单,某些情况下可能更受欢迎。
编辑:感谢Blckknght指出5
边缘情况仅在这里的某些值中发生。