362

I am looking for the best way (fast and elegant) to get a random boolean in python (flip a coin).

For the moment I am using random.randint(0, 1) or random.getrandbits(1).

Are there better choices that I am not aware of?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Xavier V.
  • 6,068
  • 6
  • 30
  • 35
  • 5
    This is a good and valid question about performance of various options for getting a random boolean, but I feel like lost in the noise of all the benchmarks is the fact that the best performer saves less than a second versus the worst performer over a _million_ iterations. If you've come here looking for a way to speed up an application, you should probably look at other options first. – Ian McLaird Oct 15 '20 at 14:16

10 Answers10

481

Adam's answer is quite fast, but I found that random.getrandbits(1) to be quite a lot faster. If you really want a boolean instead of a long then

import random
bool(random.getrandbits(1))

is still about twice as fast as random.choice([True, False])

Both solutions need to import random

If utmost speed isn't to priority then random.choice definitely reads better.

Note that random.choice() is slower than just choice() (after from random import choice) due to the attribute lookup.

$ python3 --version
Python 3.9.7
$ python3 -m timeit -s "from random import choice" "choice([True, False])"
1000000 loops, best of 5: 376 nsec per loop
$ python3 -m timeit -s "from random import choice" "choice((True, False))"
1000000 loops, best of 5: 352 nsec per loop
$ python3 -m timeit -s "from random import getrandbits" "getrandbits(1)"
10000000 loops, best of 5: 33.7 nsec per loop
$ python3 -m timeit -s "from random import getrandbits" "bool(getrandbits(1))"
5000000 loops, best of 5: 89.5 nsec per loop
$ python3 -m timeit -s "from random import getrandbits" "not getrandbits(1)"
5000000 loops, best of 5: 46.3 nsec per loop
$ python3 -m timeit -s "from random import random" "random() < 0.5"
5000000 loops, best of 5: 46.4 nsec per loop
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 29
    If we're all about performance, `not not random.getrandbits(1))` is faster than `bool` ;) – Michał Bentkowski Jul 26 '11 at 09:38
  • 17
    You likely don't even need to cast to a boolean at all, since 0/1 have the proper truth values. – Adam Vandenberg Jul 26 '11 at 16:46
  • 14
    You could speed it up further by doing `from random import getrandbits` to avoid the attribute lookup. :-) – kindall Jul 26 '11 at 23:07
  • 2
    actually, the missing attribute lookup seems to be the reason why `random() < 0.5` is the fastest. When using `from random import getrandbits` `getrandbits` is faster than `random() < 0.5`. – jl005 Feb 22 '21 at 15:27
268
import random
random.choice([True, False])

would also work.

castis
  • 8,154
  • 4
  • 41
  • 63
Adam Vandenberg
  • 19,991
  • 9
  • 54
  • 56
56

Found a faster method:

$ python -m timeit -s "from random import getrandbits" "not getrandbits(1)"
10000000 loops, best of 3: 0.222 usec per loop
$ python -m timeit -s "from random import random" "True if random() > 0.5 else False"
10000000 loops, best of 3: 0.0786 usec per loop
$ python -m timeit -s "from random import random" "random() < 0.5"
10000000 loops, best of 3: 0.0579 usec per loop
Pavel Radchenko
  • 709
  • 5
  • 4
13

I like

 np.random.rand() > .5
Maarten
  • 4,549
  • 4
  • 31
  • 36
13

If you want to generate a number of random booleans you could use numpy's random module. From the documentation

np.random.randint(2, size=10)

will return 10 random uniform integers in the open interval [0,2). The size keyword specifies the number of values to generate.

Chris
  • 44,602
  • 16
  • 137
  • 156
  • I was curious as to how the speed of this method performed against the answers since this option was left out of the comparisons. To generate one random bool (which is the question) this is much slower but if you wanted to generate many then this mecomes much faster: $ python -m timeit -s "from random import random" "random() < 0.5" 10000000 loops, best of 3: 0.0906 usec per loop – ojunk Aug 08 '18 at 10:00
6

You could use the Faker library, it's mainly used for testing, but is capable of providing a variety of fake data.

Install: https://pypi.org/project/Faker/

>>> from faker import Faker
>>> fake = Faker()
>>> fake.pybool()
True
Partiban
  • 136
  • 3
  • 9
4

I was curious as to how the speed of the numpy answer performed against the other answers since this was left out of the comparisons. To generate one random bool this is much slower but if you wanted to generate many then this becomes much faster:

$ python -m timeit -s "from random import random" "random() < 0.5"
10000000 loops, best of 3: 0.0906 usec per loop
$ python -m timeit -s "import numpy as np" "np.random.randint(2, size=1)"
100000 loops, best of 3: 4.65 usec per loop

$ python -m timeit -s "from random import random" "test = [random() < 0.5 for i in range(1000000)]"
10 loops, best of 3: 118 msec per loop
$ python -m timeit -s "import numpy as np" "test = np.random.randint(2, size=1000000)"
100 loops, best of 3: 6.31 msec per loop
ojunk
  • 879
  • 8
  • 21
3

u could try this it produces randomly generated array of true and false :

a=[bool(i) for i in np.array(np.random.randint(0,2,10))]

out: [True, True, True, True, True, False, True, False, True, False]

2

A new take on this question would involve the use of Faker which you can install easily with pip.

from faker import Factory

#----------------------------------------------------------------------
def create_values(fake):
    """"""
    print fake.boolean(chance_of_getting_true=50) # True
    print fake.random_int(min=0, max=1) # 1

if __name__ == "__main__":
    fake = Factory.create()
    create_values(fake)
Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51
Althea
  • 87
  • 1
  • 17
    You should at least explain why you think this is a better solution, considering it involves downloading a different package and is messier. – Martino Jan 13 '16 at 14:23
  • 3
    I disagree with the downvotes. If you're creating random data, you may well be in a situation where Faker is a very useful tool. The `fake.boolean()` syntax is clean and easy for others to grok. – Jason McVetta Jul 10 '17 at 05:31
  • 4
    Regardless of whether or not the package is useful, the complete lack of explanation as to why one should consider this makes the answer useless. – Apollys supports Monica Jun 09 '18 at 17:14
0

Below methods would also work for this purpose:

import random
random.choice([0, 1])

or

import random
random.choice(range(2))
Javad
  • 2,033
  • 3
  • 13
  • 23