Change the range of a uniform random number generator

I have been given the rand5 () function, which generates a random integer in a closed interval with a uniform distribution [1,5]. How can I use rand5 () and nothing else to create a rand7 () function that generates integers in [1,7] (again, evenly distributed)?


  • I searched stackoverflow and found many similar questions, but not like this one.
  • My initial attempt was rand5 () + 0.5 * rand5 () + 0.5 * rand5 (). But it will not generate integers from 1 to 7 with uniform probability. Any answers or links to answers are welcome.
+5
source share
4 answers

ok , . rand5 rand2, 0, 1. rand2 rand5,

rand2() {
    if(rand5() > 2.5) return 1
    else return 0
}

, rand2 , , rand7. , rand7, [1,2,3,4,5,6,7] rand2, 0, [1,2,3,4] rand2, 1 [3,4], 1 rand7 4. , , rand2 randx, x - .

+2

, draw5(), k: 5^k % 7 != 0 - "" .

draw5() :

, x1, x2. 5 * 5 = 25 .

, 25/7 ~ = 3.57. 3 * 7 = 21 , [1,7], 4 - .

:

(1,1),(1,2),(2,1) : 1
(3,1),(1,3),(3,2): 2
(3,3),(1,4),(4,1): 3
(2,4),(4,2)(3,4): 4
(4,3), (4,4), (1,5): 5
(5,1), (2,5), (5,2) : 6
(5,3), (3,5), (4,5) : 7
(5,4),(5,5),(2,3), (2,2) : redraw
+7

:

  • rand5() {1, 2, 4, 5} (.. 3, ).
  • {1, 2}, 1.
  • {1, 2} 0 {4, 5} 1. 3- . 0, [1, 7]. 0 1 , [1, 7] .
+4

-, : , - - , , set, .

rand5() (!), , . 7 :

In [126]: import random

In [127]: def r5():
   .....:     return random.randint(1, 5)
   .....: 

In [128]: [r5() for i in range(7)]
Out[128]: [3, 1, 3, 4, 1, 1, 2]

Obviously, each of these terms was equally one of these numbers. But only one of them turned out to be 2, therefore, if our rule were "chosen depending on which term rand5 () returns 2 for" then it would have worked. Or 4, or something else, and if we just loop long enough for this to happen. Thus, there are many ways to come up with something that works. Here (in pseudocode is terrible Python) is one way:

import random, collections

def r5():
    return random.randint(1, 5)

def r7():
    left = range(1, 8)
    while True:
        if len(left) == 1: 
            return left[0]
        rs = [r5() for n in left]
        m = max(rs)
        how_many_at_max = rs.count(m)
        if how_many_at_max == len(rs):
            # all the same: try again
            continue
        elif how_many_at_max == 1:
            # hooray!
            return left[rs.index(m)]
        # keep only the non-maximals
        left = [l for l,r in zip(left, rs) if r != m]

which gives

In [189]: collections.Counter(r7() for _ in xrange(10**6))
Out[189]: Counter({7: 143570, 5: 143206, 4: 142827, 2: 142673, 6: 142604, 1: 142573, 3: 142547})
+2
source

All Articles