396

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?

1
  • 7
    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. Commented Oct 15, 2020 at 14:16

10 Answers 10

527

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
Sign up to request clarification or add additional context in comments.

4 Comments

If we're all about performance, not not random.getrandbits(1)) is faster than bool ;)
You likely don't even need to cast to a boolean at all, since 0/1 have the proper truth values.
You could speed it up further by doing from random import getrandbits to avoid the attribute lookup. :-)
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.
287
import random
random.choice([True, False])

would also work.

4 Comments

Do I need to import some library?
Indeed - the same random used by most of the other answers here.
I really like this answer, perhaps not the fastest answer here but definitely the most readable.
57

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

5 Comments

random() > 0.5 already evaluates to a bool which is even faster!
random() >= 0.5, otherwise you will be a tiny bit biased towards False.
random() < 0.5 makes more sense as changing 0.5 to some other probability works as expected
Changed to random() < 0.5, thanks @SimonLindholm and @akxlr.
True if random() > 0.5 else False Ahhhhh!!!!!!!! My eyes.
14

I like

 np.random.rand() > .5

Comments

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.

1 Comment

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
8

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

Comments

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

Comments

3

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)

3 Comments

You should at least explain why you think this is a better solution, considering it involves downloading a different package and is messier.
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.
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.
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]

Comments

0

Below methods would also work for this purpose:

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

or

import random
random.choice(range(2))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.