首先,我想提一下,这个问题不是重复的:
Python Rounding Inconsistently
Python 3.x rounding behavior
我了解IEEE 754,并且知道:
简单的“始终向上取整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
但是我的考虑是这不是Pythonic ...根据docs,我应该使用类似以下内容:
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等指数。是否有Python方式可以做到这一点?
而且我知道我可以添加无限小的数字,而
round(num+10**(precission-20),-pricission)
可以工作,但这是错误的,以至于“幼犬会死”。 最佳答案
如您所说,如果您尝试使用大于quantize
的数字来1
则不起作用:
>>> Decimal('1.5').quantize(Decimal('10'))
Decimal('2')
>>> Decimal('1.5').quantize(Decimal('100'))
Decimal('2')
但是,您可以简单地除,量化和乘以:
from decimal import Decimal, ROUND_HALF_UP
def round_my(num, precision):
N_PLACES = Decimal(10) ** precision
# Round to n places
return (Decimal(num) / N_PLACES).quantize(1, ROUND_HALF_UP) * N_PLACES
但是,只有输入
Decimal
并与Decimal
进行比较,才能通过测试:assert round_my('1.53', -1) == Decimal('1.5')
assert round_my('1.55', -1) == Decimal('1.6')
assert round_my('1.63', -1) == Decimal('1.6')
assert round_my('1.65', -1) == Decimal('1.7')
assert round_my('1.53', -2) == Decimal('1.53')
assert round_my('1.53', -3) == Decimal('1.53')
assert round_my('1.53', 0) == Decimal('2')
assert round_my('1.53', 1) == Decimal('0')
assert round_my('15.3', 1) == Decimal('20')
assert round_my('157.3', 2) == Decimal('200')
如评论中所述,可以使用科学计数小数作为“有效的”量化参数,从而简化了函数:
def round_my(num, precision):
quant_level = Decimal('1e{}'.format(precision))
return Decimal(num).quantize(quant_level, ROUND_HALF_UP)
这也通过了上面提到的测试用例。