1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
11 class MathUtilsTest(unittest
.TestCase
):
12 """Tests for mathematical utility functions."""
14 def testTruncatedMean_EmptyList(self
):
15 # TruncatedMean raises an error when passed an empty list.
16 self
.assertRaises(TypeError, math_utils
.TruncatedMean
, [], 0)
18 def testTruncatedMean_TruncateTooMuch(self
):
19 # An exception is raised if 50% or more is truncated from both sides.
20 self
.assertRaises(TypeError, math_utils
.TruncatedMean
, [1, 2, 3], 1.0)
22 ZeroDivisionError, math_utils
.TruncatedMean
, [1, 2, 3], 0.5)
24 def testTruncatedMean_AlwaysKeepsAtLeastTwoValues(self
):
25 # If the length of the input is 1 or 2, nothing is truncated and
26 # the average is returned.
27 self
.assertEqual(5.0, math_utils
.TruncatedMean([5.0], 0.0))
28 self
.assertEqual(5.0, math_utils
.TruncatedMean([5.0], 0.25))
29 self
.assertEqual(5.0, math_utils
.TruncatedMean([5.0], 0.5))
30 self
.assertEqual(5.5, math_utils
.TruncatedMean([5.0, 6.0], 0.0))
31 self
.assertEqual(5.5, math_utils
.TruncatedMean([5.0, 6.0], 0.25))
32 self
.assertEqual(5.5, math_utils
.TruncatedMean([5.0, 6.0], 0.5))
34 def testTruncatedMean_Interquartile_NumValuesDivisibleByFour(self
):
35 self
.assertEqual(5.0, math_utils
.TruncatedMean([1, 4, 6, 100], 0.25))
37 6.5, math_utils
.TruncatedMean([1, 2, 5, 6, 7, 8, 40, 50], 0.25))
39 def testTruncatedMean_Weighting(self
):
40 # In the list [0, 1, 4, 5, 20, 100], when 25% of the list at the start
41 # and end are discarded, the part that's left is [1, 4, 5, 20], but
42 # first and last values are weighted so that they only count for half
43 # as much. So the truncated mean is (1/2 + 4 + 5 + 20/2) / 5.0.
44 self
.assertEqual(6.5, (0.5 + 4 + 5 + 10) / 3.0)
45 self
.assertEqual(6.5, math_utils
.TruncatedMean([0, 1, 4, 5, 20, 100], 0.25))
47 def testMean_OneValue(self
):
48 self
.assertEqual(3.0, math_utils
.Mean([3]))
50 def testMean_ShortList(self
):
51 self
.assertEqual(0.5, math_utils
.Mean([-3, 0, 1, 4]))
53 def testMean_CompareAlternateImplementation(self
):
54 """Tests Mean by comparing against an alternate implementation."""
55 def AlternateMean(values
):
56 return sum(values
) / float(len(values
))
61 [-3, -1, 0.12, 0.752, 3.33, 8, 16, 32, 439],
63 for value_list
in test_value_lists
:
64 self
.assertEqual(AlternateMean(value_list
), math_utils
.Mean(value_list
))
66 def testRelativeChange_NonZero(self
):
67 # The change is relative to the first value, regardless of which is bigger.
68 self
.assertEqual(0.5, math_utils
.RelativeChange(1.0, 1.5))
69 self
.assertEqual(0.5, math_utils
.RelativeChange(2.0, 1.0))
71 def testRelativeChange_FromZero(self
):
72 # If the first number is zero, then the result is not a number.
73 self
.assertEqual(0, math_utils
.RelativeChange(0, 0))
74 self
.assertTrue(math
.isnan(math_utils
.RelativeChange(0, 1)))
75 self
.assertTrue(math
.isnan(math_utils
.RelativeChange(0, -1)))
77 def testRelativeChange_Negative(self
):
78 # Note that the return value of RelativeChange is always positive.
79 self
.assertEqual(3.0, math_utils
.RelativeChange(-1, 2))
80 self
.assertEqual(3.0, math_utils
.RelativeChange(1, -2))
81 self
.assertEqual(1.0, math_utils
.RelativeChange(-1, -2))
83 def testVariance_EmptyList(self
):
84 self
.assertRaises(TypeError, math_utils
.Variance
, [])
86 def testVariance_OneValue(self
):
87 self
.assertEqual(0, math_utils
.Variance([0]))
88 self
.assertEqual(0, math_utils
.Variance([4.3]))
90 def testVariance_ShortList(self
):
91 # Population variance is the average of squared deviations from the mean.
92 # The deviations from the mean in this example are [3.5, 0.5, -0.5, -3.5],
93 # and the squared deviations are [12.25, 0.25, 0.25, 12.25].
94 # With sample variance, however, 1 is subtracted from the sample size.
95 # So the sample variance is sum([12.25, 0.25, 0.25, 12.25]) / 3.0.
96 self
.assertAlmostEqual(8.333333334, sum([12.25, 0.25, 0.25, 12.25]) / 3.0)
97 self
.assertAlmostEqual(8.333333334, math_utils
.Variance([-3, 0, 1, 4]))
99 def testStandardDeviation(self
):
100 # Standard deviation is the square root of variance.
101 self
.assertRaises(TypeError, math_utils
.StandardDeviation
, [])
102 self
.assertEqual(0.0, math_utils
.StandardDeviation([4.3]))
103 self
.assertAlmostEqual(2.88675135, math
.sqrt(8.33333333333333))
104 self
.assertAlmostEqual(2.88675135,
105 math_utils
.StandardDeviation([-3, 0, 1, 4]))
107 def testStandardError(self
):
108 # Standard error is std. dev. divided by square root of sample size.
109 self
.assertEqual(0.0, math_utils
.StandardError([]))
110 self
.assertEqual(0.0, math_utils
.StandardError([4.3]))
111 self
.assertAlmostEqual(1.44337567, 2.88675135 / math
.sqrt(4))
112 self
.assertAlmostEqual(1.44337567, math_utils
.StandardError([-3, 0, 1, 4]))
114 if __name__
== '__main__':