mirror of https://github.com/python/cpython
bpo-36324: NormalDist() add more tests and update comments (GH-12476)
* Improve coverage. * Note inherent limitations of the accuracy tests https://bugs.python.org/issue36324
This commit is contained in:
parent
aa3ecb8041
commit
2afb598618
|
@ -2040,6 +2040,13 @@ class TestStdev(VarianceStdevMixin, NumericTestCase):
|
||||||
|
|
||||||
class TestNormalDist(unittest.TestCase):
|
class TestNormalDist(unittest.TestCase):
|
||||||
|
|
||||||
|
# General note on precision: The pdf(), cdf(), and overlap() methods
|
||||||
|
# depend on functions in the math libraries that do not make
|
||||||
|
# explicit accuracy guarantees. Accordingly, some of the accuracy
|
||||||
|
# tests below may fail if the underlying math functions are
|
||||||
|
# inaccurate. There isn't much we can do about this short of
|
||||||
|
# implementing our own implementations from scratch.
|
||||||
|
|
||||||
def test_slots(self):
|
def test_slots(self):
|
||||||
nd = statistics.NormalDist(300, 23)
|
nd = statistics.NormalDist(300, 23)
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
|
@ -2062,6 +2069,12 @@ class TestNormalDist(unittest.TestCase):
|
||||||
with self.assertRaises(statistics.StatisticsError):
|
with self.assertRaises(statistics.StatisticsError):
|
||||||
statistics.NormalDist(500, -10)
|
statistics.NormalDist(500, -10)
|
||||||
|
|
||||||
|
# verify that subclass type is honored
|
||||||
|
class NewNormalDist(statistics.NormalDist):
|
||||||
|
pass
|
||||||
|
nnd = NewNormalDist(200, 5)
|
||||||
|
self.assertEqual(type(nnd), NewNormalDist)
|
||||||
|
|
||||||
def test_alternative_constructor(self):
|
def test_alternative_constructor(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
data = [96, 107, 90, 92, 110]
|
data = [96, 107, 90, 92, 110]
|
||||||
|
@ -2077,6 +2090,12 @@ class TestNormalDist(unittest.TestCase):
|
||||||
with self.assertRaises(statistics.StatisticsError):
|
with self.assertRaises(statistics.StatisticsError):
|
||||||
NormalDist.from_samples([10]) # only one input
|
NormalDist.from_samples([10]) # only one input
|
||||||
|
|
||||||
|
# verify that subclass type is honored
|
||||||
|
class NewNormalDist(NormalDist):
|
||||||
|
pass
|
||||||
|
nnd = NewNormalDist.from_samples(data)
|
||||||
|
self.assertEqual(type(nnd), NewNormalDist)
|
||||||
|
|
||||||
def test_sample_generation(self):
|
def test_sample_generation(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
mu, sigma = 10_000, 3.0
|
mu, sigma = 10_000, 3.0
|
||||||
|
@ -2099,12 +2118,6 @@ class TestNormalDist(unittest.TestCase):
|
||||||
self.assertEqual(data2, data4)
|
self.assertEqual(data2, data4)
|
||||||
self.assertNotEqual(data1, data2)
|
self.assertNotEqual(data1, data2)
|
||||||
|
|
||||||
# verify that subclass type is honored
|
|
||||||
class NewNormalDist(NormalDist):
|
|
||||||
pass
|
|
||||||
nnd = NewNormalDist(200, 5)
|
|
||||||
self.assertEqual(type(nnd), NewNormalDist)
|
|
||||||
|
|
||||||
def test_pdf(self):
|
def test_pdf(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
X = NormalDist(100, 15)
|
X = NormalDist(100, 15)
|
||||||
|
@ -2151,8 +2164,8 @@ class TestNormalDist(unittest.TestCase):
|
||||||
self.assertEqual(set(map(type, cdfs)), {float})
|
self.assertEqual(set(map(type, cdfs)), {float})
|
||||||
# Verify montonic
|
# Verify montonic
|
||||||
self.assertEqual(cdfs, sorted(cdfs))
|
self.assertEqual(cdfs, sorted(cdfs))
|
||||||
# Verify center
|
# Verify center (should be exact)
|
||||||
self.assertAlmostEqual(X.cdf(100), 0.50)
|
self.assertEqual(X.cdf(100), 0.50)
|
||||||
# Check against a table of known values
|
# Check against a table of known values
|
||||||
# https://en.wikipedia.org/wiki/Standard_normal_table#Cumulative
|
# https://en.wikipedia.org/wiki/Standard_normal_table#Cumulative
|
||||||
Z = NormalDist()
|
Z = NormalDist()
|
||||||
|
@ -2216,10 +2229,11 @@ class TestNormalDist(unittest.TestCase):
|
||||||
p = 1.0 - p
|
p = 1.0 - p
|
||||||
self.assertAlmostEqual(iq.cdf(iq.inv_cdf(p)), p)
|
self.assertAlmostEqual(iq.cdf(iq.inv_cdf(p)), p)
|
||||||
|
|
||||||
# Now apply cdf() first. At six sigmas, the round-trip
|
# Now apply cdf() first. Near the tails, the round-trip loses
|
||||||
# loses a lot of precision, so only check to 6 places.
|
# precision and is ill-conditioned (small changes in the inputs
|
||||||
for x in range(10, 190):
|
# give large changes in the output), so only check to 5 places.
|
||||||
self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=6)
|
for x in range(200):
|
||||||
|
self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=5)
|
||||||
|
|
||||||
# Error cases:
|
# Error cases:
|
||||||
with self.assertRaises(statistics.StatisticsError):
|
with self.assertRaises(statistics.StatisticsError):
|
||||||
|
@ -2237,6 +2251,9 @@ class TestNormalDist(unittest.TestCase):
|
||||||
iq.sigma = -0.1 # sigma under zero
|
iq.sigma = -0.1 # sigma under zero
|
||||||
iq.inv_cdf(0.5)
|
iq.inv_cdf(0.5)
|
||||||
|
|
||||||
|
# Special values
|
||||||
|
self.assertTrue(math.isnan(Z.inv_cdf(float('NaN'))))
|
||||||
|
|
||||||
def test_overlap(self):
|
def test_overlap(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
|
|
||||||
|
@ -2275,6 +2292,7 @@ class TestNormalDist(unittest.TestCase):
|
||||||
(NormalDist(-100, 15), NormalDist(110, 15)),
|
(NormalDist(-100, 15), NormalDist(110, 15)),
|
||||||
(NormalDist(-100, 15), NormalDist(-110, 15)),
|
(NormalDist(-100, 15), NormalDist(-110, 15)),
|
||||||
# Misc cases with unequal standard deviations
|
# Misc cases with unequal standard deviations
|
||||||
|
(NormalDist(100, 12), NormalDist(100, 15)),
|
||||||
(NormalDist(100, 12), NormalDist(110, 15)),
|
(NormalDist(100, 12), NormalDist(110, 15)),
|
||||||
(NormalDist(100, 12), NormalDist(150, 15)),
|
(NormalDist(100, 12), NormalDist(150, 15)),
|
||||||
(NormalDist(100, 12), NormalDist(150, 35)),
|
(NormalDist(100, 12), NormalDist(150, 35)),
|
||||||
|
@ -2305,18 +2323,6 @@ class TestNormalDist(unittest.TestCase):
|
||||||
self.assertEqual(X.stdev, 15)
|
self.assertEqual(X.stdev, 15)
|
||||||
self.assertEqual(X.variance, 225)
|
self.assertEqual(X.variance, 225)
|
||||||
|
|
||||||
def test_unary_operations(self):
|
|
||||||
NormalDist = statistics.NormalDist
|
|
||||||
X = NormalDist(100, 12)
|
|
||||||
Y = +X
|
|
||||||
self.assertIsNot(X, Y)
|
|
||||||
self.assertEqual(X.mu, Y.mu)
|
|
||||||
self.assertEqual(X.sigma, Y.sigma)
|
|
||||||
Y = -X
|
|
||||||
self.assertIsNot(X, Y)
|
|
||||||
self.assertEqual(X.mu, -Y.mu)
|
|
||||||
self.assertEqual(X.sigma, Y.sigma)
|
|
||||||
|
|
||||||
def test_same_type_addition_and_subtraction(self):
|
def test_same_type_addition_and_subtraction(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
X = NormalDist(100, 12)
|
X = NormalDist(100, 12)
|
||||||
|
@ -2340,13 +2346,27 @@ class TestNormalDist(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError): # __rtruediv__
|
with self.assertRaises(TypeError): # __rtruediv__
|
||||||
y / X
|
y / X
|
||||||
|
|
||||||
|
def test_unary_operations(self):
|
||||||
|
NormalDist = statistics.NormalDist
|
||||||
|
X = NormalDist(100, 12)
|
||||||
|
Y = +X
|
||||||
|
self.assertIsNot(X, Y)
|
||||||
|
self.assertEqual(X.mu, Y.mu)
|
||||||
|
self.assertEqual(X.sigma, Y.sigma)
|
||||||
|
Y = -X
|
||||||
|
self.assertIsNot(X, Y)
|
||||||
|
self.assertEqual(X.mu, -Y.mu)
|
||||||
|
self.assertEqual(X.sigma, Y.sigma)
|
||||||
|
|
||||||
def test_equality(self):
|
def test_equality(self):
|
||||||
NormalDist = statistics.NormalDist
|
NormalDist = statistics.NormalDist
|
||||||
nd1 = NormalDist()
|
nd1 = NormalDist()
|
||||||
nd2 = NormalDist(2, 4)
|
nd2 = NormalDist(2, 4)
|
||||||
nd3 = NormalDist()
|
nd3 = NormalDist()
|
||||||
|
nd4 = NormalDist(2, 4)
|
||||||
self.assertNotEqual(nd1, nd2)
|
self.assertNotEqual(nd1, nd2)
|
||||||
self.assertEqual(nd1, nd3)
|
self.assertEqual(nd1, nd3)
|
||||||
|
self.assertEqual(nd2, nd4)
|
||||||
|
|
||||||
# Test NotImplemented when types are different
|
# Test NotImplemented when types are different
|
||||||
class A:
|
class A:
|
||||||
|
|
Loading…
Reference in New Issue