From d6ea3011c500ec2fd7793ebc593bb62a2217fa8a Mon Sep 17 00:00:00 2001 From: Steven D'Aprano Date: Wed, 24 Aug 2016 12:48:12 +1000 Subject: [PATCH] Remove support for nth root of negative numbers with odd powers. Although nth roots of negative numbers are real for odd n, the statistics module doesn't make use of this. Remove support for negative roots from the private _nth_root function, which simplifies the test suite. --- Lib/statistics.py | 7 +++---- Lib/test/test_statistics.py | 29 +++++------------------------ 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/Lib/statistics.py b/Lib/statistics.py index 632127af4da..40c72db0c06 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -335,10 +335,7 @@ def float_nroot(x, n): """Handle nth root of Reals, treated as a float.""" assert isinstance(n, int) and n > 1 if x < 0: - if n%2 == 0: - raise ValueError('domain error: even root of negative number') - else: - return -_nroot_NS.nroot(-x, n) + raise ValueError('domain error: root of negative number') elif x == 0: return math.copysign(0.0, x) elif x > 0: @@ -433,6 +430,8 @@ def decimal_nroot(x, n): else: # Preserve the input NAN. return x + if x < 0: + raise ValueError('domain error: root of negative number') if x.is_infinite(): return x # FIXME this hasn't had the extensive testing of the float diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index dff0cd4476b..9443ff0c61f 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1095,13 +1095,6 @@ def test_inf(self): with self.subTest(n=n, inf=INF): self.assertEqual(self.nroot(INF, n), INF) - def testNInf(self): - # Test that the root of -inf is -inf for odd n. - for NINF in (float('-inf'), decimal.Decimal('-inf')): - for n in range(3, 11, 2): - with self.subTest(n=n, inf=NINF): - self.assertEqual(self.nroot(NINF, n), NINF) - # FIXME: need to check Decimal zeroes too. def test_zero(self): # Test that the root of +0.0 is +0.0. @@ -1157,13 +1150,15 @@ def testBadTypes(self): with self.subTest(x=x): self.assertRaises(TypeError, self.nroot, x, 3) - def testNegativeEvenPower(self): - # Test negative x with even n raises correctly. + def testNegativeError(self): + # Test negative x raises correctly. x = random.uniform(-20.0, -0.1) assert x < 0 - for n in range(2, 9, 2): + for n in range(3, 7): with self.subTest(x=x, n=n): self.assertRaises(ValueError, self.nroot, x, n) + # And Decimal. + self.assertRaises(ValueError, self.nroot, Decimal(-27), 3) # --- Test that nroot is never worse than calling math.pow() --- @@ -1216,25 +1211,11 @@ def testExactPowers(self): x = i**n self.assertEqual(self.nroot(x, n), i) - def testExactPowersNegatives(self): - # Test that small negative integer powers are calculated exactly. - for i in range(-1, -51, -1): - for n in range(3, 16, 2): - if (i, n) == (-35, 13): - # See testExpectedFailure35p13 - continue - with self.subTest(i=i, n=n): - x = i**n - assert sign(x) == -1 - self.assertEqual(self.nroot(x, n), i) - def testExpectedFailure35p13(self): # Test the expected failure 35**13 is almost exact. x = 35**13 err = abs(self.nroot(x, 13) - 35) self.assertLessEqual(err, 0.000000001) - err = abs(self.nroot(-x, 13) + 35) - self.assertLessEqual(err, 0.000000001) def testOne(self): # Test that the root of 1.0 is 1.0.