Search code examples
pythonrandombell-curve

python random binary list, evenly distributed


I have code to make a binary list of any length I want, with a random number of bits turned on:

rand_binary_list = lambda n: [random.randint(0,1) for b in range(1,n+1)]
rand_binary_list(10)

this returns something like this:

[0,1,1,0,1,0,1,0,0,0]

and if you run it a million times you'll get a bell curve distribution where about the sum(rand_binary_list(10)) is about 5 way more often than 1 or 10.

What I'd prefer is that having 1 bit turned on out of 10 is equally as likely as having half of them turned on. The number of bits turned on should be uniformly distributed.

I'm not sure how this can be done without compromising the integrity of the randomness. Any ideas?

EDIT:

I wanted to show this bell curve phenomenon explicitly so here it is:

>>> import random
>>> rand_binary_list = lambda n: [random.randint(0,1) for b in range(1,n+1)]
>>> counts = {0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0}
>>> for i in range(10000):
...     x = sum(rand_binary_list(10))
...     counts[x] = counts[x] + 1
...
>>> counts[0]
7
>>> counts[1]
89
>>> counts[2]
454
>>> counts[3]
1217
>>> counts[4]
2017
>>> counts[5]
2465
>>> counts[6]
1995
>>> counts[7]
1183
>>> counts[8]
460
>>> counts[9]
107
>>> counts[10]
6

see how the chances of getting 5 turned on are much higher than the chances of getting 1 bit turned on?


Solution

  • Something like this:

    def randbitlist(n=10):
        n_on = random.randint(0, n)
        n_off = n - n_on
        result = [1]*n_on + [0]*n_off
        random.shuffle(result)
        return result
    

    The number of bits "on" should be uniformly distributed in [0, n] inclusive, and then those bits selected will be uniformly distributed throughout the list.