]> granicus.if.org Git - python/commitdiff
Close #20536: correctly handle Decimal exponents in statistics
authorNick Coghlan <ncoghlan@gmail.com>
Sat, 8 Feb 2014 13:55:14 +0000 (23:55 +1000)
committerNick Coghlan <ncoghlan@gmail.com>
Sat, 8 Feb 2014 13:55:14 +0000 (23:55 +1000)
Lib/statistics.py
Lib/test/test_statistics.py
Misc/NEWS

index e1dfbd49317bddc373f5d0eb0fb75ffeb4eb4cea..25a26d4aa713bfe8551667d4dc86a57aff2b66ea 100644 (file)
@@ -243,9 +243,13 @@ def _decimal_to_ratio(d):
     num = 0
     for digit in digits:
         num = num*10 + digit
+    if exp < 0:
+        den = 10**-exp
+    else:
+        num *= 10**exp
+        den = 1
     if sign:
         num = -num
-    den = 10**-exp
     return (num, den)
 
 
index 49b8597a91bcc98b640f0b3a920f46642c86417e..6f5c9a649d4273eb39fbbd45e423c2d2cb0227f4 100644 (file)
@@ -686,6 +686,38 @@ class DecimalToRatioTest(unittest.TestCase):
         for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')):
             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):
     # Test _check_type private function.
@@ -1074,6 +1106,12 @@ class TestMean(NumericTestCase, AverageMixin, UnivariateTypeMixin):
         actual = self.func(data*2)
         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):
     # Common tests for median and all median.* functions.
index 10ebee27b37e8ce735c7d17e20eb201f56e96866..028f4d2224dd12f2a2db853209bbcc3f69fc970f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@ Core and Builtins
 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
   filters out illegal values and correctly allows any valid prefix length.