7

I want to generate a random boolean for use in a game, so it does not need to be cryptographically secure. I will use stdbool.h in my code, and I have also done #include <stdlib.h>. Preferably, it should be very fast (as I will be generating many of them), and it should be able to be done in C89 (just preference). I am not interested at all in doing this in C++.

Here are some of the ways I've come up with:

  • read from /dev/urandom, filter out single digits and >5 = true, <5 = false.
  • keep calling rand() and filter out low/high values.
sadljkfhalskdjfh
  • 747
  • 3
  • 10
  • 17
  • If you call `rand`, you can perform `% 2` on the result to get a 0 or 1. – Fiddling Bits Oct 11 '15 at 02:15
  • `> 5` = true, `< 5` = false means you'll get true most of the time, unless you extract only 3 bits from `/dev/urandom` stream, then you'll get false most of the time – phuclv Oct 11 '15 at 03:15

2 Answers2

12

Just call rand() and get the LSB of its return value.

bool randbool = rand() & 1;

Remember to call srand() at the beginning.

timrau
  • 22,578
  • 4
  • 51
  • 64
  • 1
    Same result, but `% 2` may be a little clearer (i.e. self documenting). – Fiddling Bits Oct 11 '15 at 02:17
  • 1
    I think `& 1` may generate more efficient code (when not optimized) – Michael Petch Oct 11 '15 at 02:44
  • 2
    A good optimising compiler will make the most efficient code regardless which one you use. Better to program for readability and clarity than trying to hand optimise. – waterjuice Oct 11 '15 at 02:49
  • 8
    This is an antipattern because the low order bit generated by rand may not be very random. Its better to compare with `RAND_MAX/2`. (See the Notes section in the manpage http://man7.org/linux/man-pages/man3/rand.3.html) – rici Oct 11 '15 at 02:55
  • @aterjuice, Fiddling Bits `&1` and `%2` are not functional equivalent with an `int` argument. Best to use `rand() & 1` here. – chux - Reinstate Monica Oct 11 '15 at 03:32
  • 4
    This is a very bad practice. The implementation of rand() rely on linear congruential generators (LCGs), which are notoriously problematic pseudo-random number generators. They lack randomness at lower bits of the output. You should at least take the most significant bit. – plasmacel Aug 03 '16 at 21:47
  • https://stackoverflow.com/a/50257035/918959 – Antti Haapala -- Слава Україні Aug 25 '19 at 07:04
  • It's random enough for many purposes, running INT_MAX times, it's fairly balanced also: zero: 1073738760 one: 1073744887 – ericcurtin Dec 17 '20 at 18:14
1

If you have RDRAND instruction set on a x86_64 CPU:

#include <immintrin.h>
#include <cstdint>
...
bool randBool() {
  uint64_t val;
  if(!_rdseed64_step(&val)) {
    printf("Error generating hardware random value\n");
  }
  return bool(val&1);
}

However, this wastes 63 out of 64 pseudo-random bits generated. If you need more speed, call _rdseed64_step() once in 64 random bit generations, but change the bit tested in each generation: val&(1<<0) , val & (1<<1), val & (1<<2), val & (1<<3), ... , val & (1<<i), ..., val & (1<<63) .

Serge Rogatch
  • 13,865
  • 7
  • 86
  • 158