Commit 720bb69e authored by Nick Coghlan's avatar Nick Coghlan

Close #20536: correctly handle Decimal exponents in statistics

parent e3270e7b
...@@ -243,9 +243,13 @@ def _decimal_to_ratio(d): ...@@ -243,9 +243,13 @@ def _decimal_to_ratio(d):
num = 0 num = 0
for digit in digits: for digit in digits:
num = num*10 + digit num = num*10 + digit
if exp < 0:
den = 10**-exp
else:
num *= 10**exp
den = 1
if sign: if sign:
num = -num num = -num
den = 10**-exp
return (num, den) return (num, den)
......
...@@ -686,6 +686,38 @@ class DecimalToRatioTest(unittest.TestCase): ...@@ -686,6 +686,38 @@ class DecimalToRatioTest(unittest.TestCase):
for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')): for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')):
self.assertRaises(ValueError, statistics._decimal_to_ratio, d) self.assertRaises(ValueError, statistics._decimal_to_ratio, d)
def test_sign(self):
# Test sign is calculated correctly.
numbers = [Decimal("9.8765e12"), Decimal("9.8765e-12")]
for d in numbers:
# First test positive decimals.
assert d > 0
num, den = statistics._decimal_to_ratio(d)
self.assertGreaterEqual(num, 0)
self.assertGreater(den, 0)
# Then test negative decimals.
num, den = statistics._decimal_to_ratio(-d)
self.assertLessEqual(num, 0)
self.assertGreater(den, 0)
def test_negative_exponent(self):
# Test result when the exponent is negative.
t = statistics._decimal_to_ratio(Decimal("0.1234"))
self.assertEqual(t, (1234, 10000))
def test_positive_exponent(self):
# Test results when the exponent is positive.
t = statistics._decimal_to_ratio(Decimal("1.234e7"))
self.assertEqual(t, (12340000, 1))
def test_regression_20536(self):
# Regression test for issue 20536.
# See http://bugs.python.org/issue20536
t = statistics._decimal_to_ratio(Decimal("1e2"))
self.assertEqual(t, (100, 1))
t = statistics._decimal_to_ratio(Decimal("1.47e5"))
self.assertEqual(t, (147000, 1))
class CheckTypeTest(unittest.TestCase): class CheckTypeTest(unittest.TestCase):
# Test _check_type private function. # Test _check_type private function.
...@@ -1074,6 +1106,12 @@ class TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin): ...@@ -1074,6 +1106,12 @@ class TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin):
actual = self.func(data*2) actual = self.func(data*2)
self.assertApproxEqual(actual, expected) self.assertApproxEqual(actual, expected)
def test_regression_20561(self):
# Regression test for issue 20561.
# See http://bugs.python.org/issue20561
d = Decimal('1e4')
self.assertEqual(statistics.mean([d]), d)
class TestMedian(NumericTestCase, AverageMixin): class TestMedian(NumericTestCase, AverageMixin):
# Common tests for median and all median.* functions. # Common tests for median and all median.* functions.
......
...@@ -27,6 +27,9 @@ Core and Builtins ...@@ -27,6 +27,9 @@ Core and Builtins
Library Library
------- -------
- Issue #20536: the statistics module now correctly handle Decimal instances
with positive exponents
- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably - Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably
filters out illegal values and correctly allows any valid prefix length. filters out illegal values and correctly allows any valid prefix length.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment