Skip to content

Commit 720bb69

Browse files
committed
Close #20536: correctly handle Decimal exponents in statistics
1 parent e3270e7 commit 720bb69

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

Lib/statistics.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,13 @@ def _decimal_to_ratio(d):
243243
num = 0
244244
for digit in digits:
245245
num = num*10 + digit
246+
if exp < 0:
247+
den = 10**-exp
248+
else:
249+
num *= 10**exp
250+
den = 1
246251
if sign:
247252
num = -num
248-
den = 10**-exp
249253
return (num, den)
250254

251255

Lib/test/test_statistics.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,38 @@ def testSpecialsRaise(self):
686686
for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')):
687687
self.assertRaises(ValueError, statistics._decimal_to_ratio, d)
688688

689+
def test_sign(self):
690+
# Test sign is calculated correctly.
691+
numbers = [Decimal("9.8765e12"), Decimal("9.8765e-12")]
692+
for d in numbers:
693+
# First test positive decimals.
694+
assert d > 0
695+
num, den = statistics._decimal_to_ratio(d)
696+
self.assertGreaterEqual(num, 0)
697+
self.assertGreater(den, 0)
698+
# Then test negative decimals.
699+
num, den = statistics._decimal_to_ratio(-d)
700+
self.assertLessEqual(num, 0)
701+
self.assertGreater(den, 0)
702+
703+
def test_negative_exponent(self):
704+
# Test result when the exponent is negative.
705+
t = statistics._decimal_to_ratio(Decimal("0.1234"))
706+
self.assertEqual(t, (1234, 10000))
707+
708+
def test_positive_exponent(self):
709+
# Test results when the exponent is positive.
710+
t = statistics._decimal_to_ratio(Decimal("1.234e7"))
711+
self.assertEqual(t, (12340000, 1))
712+
713+
def test_regression_20536(self):
714+
# Regression test for issue 20536.
715+
# See http://bugs.python.org/issue20536
716+
t = statistics._decimal_to_ratio(Decimal("1e2"))
717+
self.assertEqual(t, (100, 1))
718+
t = statistics._decimal_to_ratio(Decimal("1.47e5"))
719+
self.assertEqual(t, (147000, 1))
720+
689721

690722
class CheckTypeTest(unittest.TestCase):
691723
# Test _check_type private function.
@@ -1074,6 +1106,12 @@ def test_doubled_data(self):
10741106
actual = self.func(data*2)
10751107
self.assertApproxEqual(actual, expected)
10761108

1109+
def test_regression_20561(self):
1110+
# Regression test for issue 20561.
1111+
# See http://bugs.python.org/issue20561
1112+
d = Decimal('1e4')
1113+
self.assertEqual(statistics.mean([d]), d)
1114+
10771115

10781116
class TestMedian(NumericTestCase, AverageMixin):
10791117
# Common tests for median and all median.* functions.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ Core and Builtins
2727
Library
2828
-------
2929

30+
- Issue #20536: the statistics module now correctly handle Decimal instances
31+
with positive exponents
32+
3033
- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably
3134
filters out illegal values and correctly allows any valid prefix length.
3235

0 commit comments

Comments
 (0)