首先我想提到这个问题不是重复的:
Python Rounding Inconsistently
Python 3.x rounding behavior
我知道IEEE 754,并且我知道:
“简单的“始终将0.5四舍五入”技术会导致略微偏向更高的数字。在大量计算时,这可能是重要的。 Python 3.0方法消除了这个问题。”
我同意ROUND_HALF_UP方法比Python默认实现的方法差。尽管如此,有些人不知道这一点,如果规范要求,就需要使用该方法。使其起作用的简单方法是:
但我认为这不符合Python风格...根据文档,我应该使用类似以下方式的代码:
问题是这样做不能通过所有测试案例:
由于浮点数和十进制数之间的转换性质,以及量化似乎不能处理指数为10或100的情况。有没有Pythonic的方法来解决这个问题?
我知道我可以添加无限小的数字,然后使用
“简单的“始终将0.5四舍五入”技术会导致略微偏向更高的数字。在大量计算时,这可能是重要的。 Python 3.0方法消除了这个问题。”
我同意ROUND_HALF_UP方法比Python默认实现的方法差。尽管如此,有些人不知道这一点,如果规范要求,就需要使用该方法。使其起作用的简单方法是:
def round_my(num, precission):
exp = 2*10**(-precission)
temp = num * exp
if temp%2 < 1:
return int(temp - temp%2)/exp
else:
return int(temp - temp%2 + 2)/exp
但我认为这不符合Python风格...根据文档,我应该使用类似以下方式的代码:
def round_my(num, pricission):
N_PLACES = Decimal(10) ** pricission # same as Decimal('0.01')
# Round to n places
Decimal(num).quantize(N_PLACES)
问题是这样做不能通过所有测试案例:
class myRound(unittest.TestCase):
def test_1(self):
self.assertEqual(piotrSQL.round_my(1.53, -1), 1.5)
self.assertEqual(piotrSQL.round_my(1.55, -1), 1.6)
self.assertEqual(piotrSQL.round_my(1.63, -1), 1.6)
self.assertEqual(piotrSQL.round_my(1.65, -1), 1.7)
self.assertEqual(piotrSQL.round_my(1.53, -2), 1.53)
self.assertEqual(piotrSQL.round_my(1.53, -3), 1.53)
self.assertEqual(piotrSQL.round_my(1.53, 0), 2)
self.assertEqual(piotrSQL.round_my(1.53, 1), 0)
self.assertEqual(piotrSQL.round_my(15.3, 1), 20)
self.assertEqual(piotrSQL.round_my(157.3, 2), 200)
由于浮点数和十进制数之间的转换性质,以及量化似乎不能处理指数为10或100的情况。有没有Pythonic的方法来解决这个问题?
我知道我可以添加无限小的数字,然后使用
round(num+10**(precission-20),-pricission)
,但这是非常错误的,"小狗会死掉"……
1.65
不会被认为是“四舍五入”的,因为它实际上是1.649999999999999911182158029987...
吗? - MSeifertfloat
类型。无法还原创建float
的字符串。在整个代码中保持它们为字符串或十进制数以避免这种“陷阱”。 - MSeifert