mirror of
https://github.com/python/cpython.git
synced 2024-11-28 12:31:14 +08:00
bpo-30561: Sync-up expovariate() and gammavariate code (GH-1934)
This commit is contained in:
parent
b7105c9c96
commit
63d152232e
@ -582,10 +582,7 @@ class Random(_random.Random):
|
||||
|
||||
elif alpha == 1.0:
|
||||
# expovariate(1/beta)
|
||||
u = random()
|
||||
while u <= 1e-7:
|
||||
u = random()
|
||||
return -_log(u) * beta
|
||||
return -_log(1.0 - random()) * beta
|
||||
|
||||
else: # alpha is between 0 and 1 (exclusive)
|
||||
|
||||
|
@ -853,28 +853,48 @@ class TestDistributions(unittest.TestCase):
|
||||
self.assertRaises(ValueError, random.gammavariate, 2, 0)
|
||||
self.assertRaises(ValueError, random.gammavariate, 1, -3)
|
||||
|
||||
# There are three different possibilities in the current implementation
|
||||
# of random.gammavariate(), depending on the value of 'alpha'. What we
|
||||
# are going to do here is to fix the values returned by random() to
|
||||
# generate test cases that provide 100% line coverage of the method.
|
||||
@unittest.mock.patch('random.Random.random')
|
||||
def test_gammavariate_full_code_coverage(self, random_mock):
|
||||
# There are three different possibilities in the current implementation
|
||||
# of random.gammavariate(), depending on the value of 'alpha'. What we
|
||||
# are going to do here is to fix the values returned by random() to
|
||||
# generate test cases that provide 100% line coverage of the method.
|
||||
def test_gammavariate_alpha_greater_one(self, random_mock):
|
||||
|
||||
# #1: alpha > 1.0: we want the first random number to be outside the
|
||||
# #1: alpha > 1.0.
|
||||
# We want the first random number to be outside the
|
||||
# [1e-7, .9999999] range, so that the continue statement executes
|
||||
# once. The values of u1 and u2 will be 0.5 and 0.3, respectively.
|
||||
random_mock.side_effect = [1e-8, 0.5, 0.3]
|
||||
returned_value = random.gammavariate(1.1, 2.3)
|
||||
self.assertAlmostEqual(returned_value, 2.53)
|
||||
|
||||
# #2: alpha == 1: first random number less than 1e-7 to that the body
|
||||
# of the while loop executes once. Then random.random() returns 0.45,
|
||||
# which causes while to stop looping and the algorithm to terminate.
|
||||
random_mock.side_effect = [1e-8, 0.45]
|
||||
returned_value = random.gammavariate(1.0, 3.14)
|
||||
self.assertAlmostEqual(returned_value, 2.507314166123803)
|
||||
@unittest.mock.patch('random.Random.random')
|
||||
def test_gammavariate_alpha_equal_one(self, random_mock):
|
||||
|
||||
# #3: 0 < alpha < 1. This is the most complex region of code to cover,
|
||||
# #2.a: alpha == 1.
|
||||
# The execution body of the while loop executes once.
|
||||
# Then random.random() returns 0.45,
|
||||
# which causes while to stop looping and the algorithm to terminate.
|
||||
random_mock.side_effect = [0.45]
|
||||
returned_value = random.gammavariate(1.0, 3.14)
|
||||
self.assertAlmostEqual(returned_value, 1.877208182372648)
|
||||
|
||||
@unittest.mock.patch('random.Random.random')
|
||||
def test_gammavariate_alpha_equal_one_equals_expovariate(self, random_mock):
|
||||
|
||||
# #2.b: alpha == 1.
|
||||
# It must be equivalent of calling expovariate(1.0 / beta).
|
||||
beta = 3.14
|
||||
random_mock.side_effect = [1e-8, 1e-8]
|
||||
gammavariate_returned_value = random.gammavariate(1.0, beta)
|
||||
expovariate_returned_value = random.expovariate(1.0 / beta)
|
||||
self.assertAlmostEqual(gammavariate_returned_value, expovariate_returned_value)
|
||||
|
||||
@unittest.mock.patch('random.Random.random')
|
||||
def test_gammavariate_alpha_between_zero_and_one(self, random_mock):
|
||||
|
||||
# #3: 0 < alpha < 1.
|
||||
# This is the most complex region of code to cover,
|
||||
# as there are multiple if-else statements. Let's take a look at the
|
||||
# source code, and determine the values that we need accordingly:
|
||||
#
|
||||
|
@ -0,0 +1,4 @@
|
||||
random.gammavariate(1.0, beta) now computes the same result as
|
||||
random.expovariate(1.0 / beta). This synchonizes the two algorithms and
|
||||
eliminates some idiosyncrasies in the old implementation. It does however
|
||||
produce a difference stream of random variables than it used to.
|
Loading…
Reference in New Issue
Block a user