I am new to C programming, and i've read that erand48() is a good option for thread-safe random number generation. However the function takes a seed value of: unsigned short int array[3]
Any recommendations as to what this seed value should be initialized to?
Alright. So first, let me make it clear that the PRNG in
libc
is deterministic (that's why it wants a seed), uses an LCG - meaning it's easy to predict all of the values once you have a few, and is therefore insecure.Now then.
erand48()
returns a random floating point value ofdouble
size from a uniform distribution of pseudorandom real numbers. It doesn't take a seed value per se, but rather requires you to provide a state buffer. Here's the full declaration:The state buffer, amusingly enough, must be seeded by a random value in order for the generator to work. My first thought was to read from
/dev/urandom
.We can do that with something like this (using unbuffered reads to prevent wastage from such small reads):
This is thread safe, and even ensures a relatively safe seed value for all of the threads.
Of course, if speed isn't too much of an issue (ie: you can live with a small loss of speed) and you can live with integers, then doing unbuffered reads directly from
/dev/urandom
is a perfect solution. Even better, /dev/urandom provides secure, unpredictable pseudorandom integers (well, technically, a byte stream, but they will always work as integers as long as you match the size) that are also usually uniformly distributed.Plus,
/dev/urandom
periodically has entropy injected into it and refreshed, ensuring that you have a decent supply of fairly random numbers.Just my 2 cents...
We used the same function-family in one of our projects sometime ago. The product had to work on Windows/Unix, so we did not use /dev/random.
Instead, we concatenated the host_ip_addr + time() + process_id + thread_id as a string and generated a hash from this string. And then, we spread XOR'ed the trailing bytes onto the 6 leading bytes. We used that final data as our seed...
The rand48 family is a 48 bit LCG, meaning something like
... except that I've never seen a computer with an uint48_t, so what you pass around is an array with 48 bits of state (3x16 assuming that a short has 16 bits). You can seed it with anything - just get 48 random bits and shove them into array[3], from /dev/urandom, from time/pid/whatever.
A few gotchas: - lcong48() - forget it even exists - "how do I make sure that two seeds are not ridiculously close to each other?" - don't, it would take less time to just use another rng.