Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 44 additions & 24 deletions Lib/test/test_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,13 @@ def test_compare_to_variance(self):

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):
nd = statistics.NormalDist(300, 23)
with self.assertRaises(TypeError):
Expand All @@ -2062,6 +2069,12 @@ def test_instantiation_and_attributes(self):
with self.assertRaises(statistics.StatisticsError):
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):
NormalDist = statistics.NormalDist
data = [96, 107, 90, 92, 110]
Expand All @@ -2077,6 +2090,12 @@ def test_alternative_constructor(self):
with self.assertRaises(statistics.StatisticsError):
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):
NormalDist = statistics.NormalDist
mu, sigma = 10_000, 3.0
Expand All @@ -2099,12 +2118,6 @@ def test_sample_generation(self):
self.assertEqual(data2, data4)
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):
NormalDist = statistics.NormalDist
X = NormalDist(100, 15)
Expand Down Expand Up @@ -2151,8 +2164,8 @@ def test_cdf(self):
self.assertEqual(set(map(type, cdfs)), {float})
# Verify montonic
self.assertEqual(cdfs, sorted(cdfs))
# Verify center
self.assertAlmostEqual(X.cdf(100), 0.50)
# Verify center (should be exact)
self.assertEqual(X.cdf(100), 0.50)
# Check against a table of known values
# https://en.wikipedia.org/wiki/Standard_normal_table#Cumulative
Z = NormalDist()
Expand Down Expand Up @@ -2216,10 +2229,11 @@ def test_inv_cdf(self):
p = 1.0 - p
self.assertAlmostEqual(iq.cdf(iq.inv_cdf(p)), p)

# Now apply cdf() first. At six sigmas, the round-trip
# loses a lot of precision, so only check to 6 places.
for x in range(10, 190):
self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=6)
# Now apply cdf() first. Near the tails, the round-trip loses
# precision and is ill-conditioned (small changes in the inputs
# give large changes in the output), so only check to 5 places.
for x in range(200):
self.assertAlmostEqual(iq.inv_cdf(iq.cdf(x)), x, places=5)

# Error cases:
with self.assertRaises(statistics.StatisticsError):
Expand All @@ -2237,6 +2251,9 @@ def test_inv_cdf(self):
iq.sigma = -0.1 # sigma under zero
iq.inv_cdf(0.5)

# Special values
self.assertTrue(math.isnan(Z.inv_cdf(float('NaN'))))

def test_overlap(self):
NormalDist = statistics.NormalDist

Expand Down Expand Up @@ -2275,6 +2292,7 @@ def overlap_numeric(X, Y, *, steps=8_192, z=5):
(NormalDist(-100, 15), NormalDist(110, 15)),
(NormalDist(-100, 15), NormalDist(-110, 15)),
# Misc cases with unequal standard deviations
(NormalDist(100, 12), NormalDist(100, 15)),
(NormalDist(100, 12), NormalDist(110, 15)),
(NormalDist(100, 12), NormalDist(150, 15)),
(NormalDist(100, 12), NormalDist(150, 35)),
Expand Down Expand Up @@ -2305,18 +2323,6 @@ def test_properties(self):
self.assertEqual(X.stdev, 15)
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):
NormalDist = statistics.NormalDist
X = NormalDist(100, 12)
Expand All @@ -2340,13 +2346,27 @@ def test_translation_and_scaling(self):
with self.assertRaises(TypeError): # __rtruediv__
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):
NormalDist = statistics.NormalDist
nd1 = NormalDist()
nd2 = NormalDist(2, 4)
nd3 = NormalDist()
nd4 = NormalDist(2, 4)
self.assertNotEqual(nd1, nd2)
self.assertEqual(nd1, nd3)
self.assertEqual(nd2, nd4)

# Test NotImplemented when types are different
class A:
Expand Down