views:

422

answers:

9

What would be the fastest way to generate a large number of (pseudo-)random bits. Each bit must be independent and be zero or one with equal probability. I could obviously do some variation on

randbit=rand()%2;

but I feel like there should be a faster way, generating several random bits from each call to the random number generator. Ideally I'd like to get an int or a char where each bit is random and independent, but other solutions are also possible.

The application is not cryptographic in nature so strong randomness isn't a major factor, whereas speed and getting the correct distribution is important.

+4  A: 

Take a look at Boost.Random, especially boost::uniform_int<>.

avakar
+3  A: 

As you say just generate random integers.
Then you have 32 random bits with ones and zeroes all equally probable.

Get the bits in a loop:

for (int i = 0; i < 32; i++)
{
  randomBit = (randomNum >> i) & 1
  ...
  // Do your thing
}

Repeat this for as many times you need to to get the correct amount of bits.

Sani Huttunen
rand is not guaranteed to return 32 random bits. In fact under msvc, it only returns 16.
avakar
Ofcourse it's platform dependent but the principle is still the same regardless of platform.
Sani Huttunen
Are they really equally distributed? I considered this idea, but couldn't quite convince myself that each bit would be equally and independently distributed.
That depends on the amount of bits. In smaller subsets you can find skewed distributions but the larger the set the more uniform the distribution will become. Since you specifically wanted a large number of bits this should satisfy your distribution correctness.
Sani Huttunen
I think that the distribution for each bit actually are *not* eaqually probable for the least significant bits.
KarlP
Care to elaborate on that? (Since you obviously downvoted).
Sani Huttunen
Common RNGs have a completely non-random LSB (always flips).
MSalters
This is not a question of RNGs (or answer on RNGs) this is an algorithm question. Regardless of the RNG. Since there are 2^32 possible numbers and the bit distribution is exactly equal, not somewhat equal or nearly equal or even almost equal but EXACTLY equal, the distribution of bits will be more and more uniform the larger the set is.
Sani Huttunen
I agree, if you don't limit the max outcome of rand they are equally distributed.
DaClown
+1  A: 

SMP Safe (i.e. Fastest way possiable these days) and good bits

Note the use of the [ThreadStatic] attribute, this object automatically handle's new thread's, no locking. That's the only way your going to ensure high-performance random, SMP lockfree.

http://blogs.msdn.com/pfxteam/archive/2009/02/19/9434171.aspx

RandomNickName42
Very interesting article, thanks
A: 

You can generate a random number and keep on right shifitng and testing the least significant bit to get the random bits instead of doing a mod operation.

Naveen
+3  A: 

convert a random number into binary
Why not get just one number (of appropriate size to get enough bits you need) and then convert it to binary. You'll actually get bits from a random number which means they are random as well.

Zeros and ones also have the probability of 50%, since taking all numbers between 0 and some 2^n limit and counting the number of zeros and ones are equal > meaning that probability of zeros and ones is the same.

regarding speed
this would probably be very fast, since getting just one random number compared to number of bits in it is faster. it purely depends on your binary conversion now.

Robert Koritnik
A: 

Just read some memory - take a n bit section of raw memory. It will be pretty random.

Alternatively, generate a large random int x and just use the bit values.

for(int i = (bitcount-1); i >= 0 ; i--) bin += x & (1 << i);
Antony Carthy
Memory does not contain random data, quite the contrary actually: they have been put there in a structured fashion by an application.
soulmerge
The bits will be randomly arranged for all intents and purposes, since structure is relevant to meaning. e.g. "my dog" is an ordered piece of data, but its binary is 011011010111100100100000011001000110111101100111, which is pretty random. Please give me back my +1 since I am correct.
Antony Carthy
Taking raw memory in general is not a good idea! E.g. in your example of an ASCII string, every 8th bit is 0 as valid characters use only the lower 7 bits. More over, it seems that bytes of 0 are quite common (padding, unused memory, numbers that to not use the full range, bools stored in int32, ...) so you could expect more 0s then 1s.
Chris
Agreed. I did think this as I posted the above, but the second method will work fine...
Antony Carthy
A: 

If I rememeber correctly, the least significant bits are normally having a "less random" distribution for most pseuodo random number generators, so using modulo and/or each bit in the generated number would be bad if you are worried about the distribution.

(Maybe you should at least google what Knuth says...)

If that holds ( and its hard to tell without knowing exactly what algorithm you are using) just use the highest bit in each generated number.

http://en.wikipedia.org/wiki/Pseudo-random

KarlP
A: 

How large do you need the number of generated bits to be? If it is not larger than a few million, and keeping in mind that you are not using the generator for cryptography, then I think the fastest possible way would be to precompute a large set of integers with the correct distribution, convert it to a text file like this:

unsigned int numbers[] =
{
  0xABCDEF34, ...
};

and then compile the array into your program and go through it one number at a time.

That way you get 32 bits with every call (on a 32-bit processor), the generation time is the shortest possible because all the numbers are generated in advance, and the distribution is controlled by you. The downside is, of course, that these numbers are not random at all, which depending on what you are using the PRNG for may or may not matter.

ajanicij
+1  A: 

Here's a very fast one I coded in Java based on George Marsaglia's XORShift algorithm: gets you 64 bits at a time!

/**
 * State for random number generation
 */
private static volatile long state=xorShift64(System.nanoTime()|0xCAFEBABE);

/**
 * Gets a long random value
 * @return Random long value based on static state
 */
public static final long nextLong() {
    long a=state;
    state = xorShift64(a);
    return a;
}

/**
 * XORShift algorithm - credit to George Marsaglia!
 * @param a Initial state
 * @return new state
 */
public static final long xorShift64(long a) {
    a ^= (a << 21);
    a ^= (a >>> 35);
    a ^= (a << 4);
    return a;
}
mikera
Note: the reason that this algorithm is so fast is that it just uses simple bitwise operators, in a sequence that have been proven (Marsaglia) to generate a "good enough" psuedo random sequence. This is *not* cryptographically strong but is good enough for games, simulations etc.
mikera