Reputation: 26333
I heard that computation results can be very sensitive to choice of random number generator.
1 I wonder whether it is relevant to program own Mersenne-Twister or other pseudo-random routines to get a good number generator. Also, I don't see why I should not trust native or library generators as random.uniform() in numpy, rand() in C++. I understand that I can build generators on my own for distributions other than uniform (inverse repartition function methor, polar method). But is it evil to use one built-in generator for uniform sampling?
2 What is wrong with the default 'time' seed? Should one re-seed and how frequently in a code sample (and why)?
3 Maybe you have some good links on these topics!
--edit More precisely, I need random numbers for multistart optimization routines, and for uniform space sample to initialize some other optimization routine parameters. I also need random numbers for Monte Carlo methods (sensibility analysis). I hope the precisions help figure out the scope of question.
Upvotes: 2
Views: 3716
Reputation: 88155
In C++ the <random>
library probably provides all you need. It has 3 different PRNG template algorithms including mersenne twister, 3 adaptors for use on top of those, 9 concrete random number generators, plus access to your system's non-deterministic random number source.
On top of that it has 20 random number distributions that include uniform, normal, bernoulli, poisson, and sampling distributions.
Here's a (slightly modified) example from Stroustrup's C++11 FAQ.
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional>
int main()
{
auto rand = std::bind(
std::normal_distribution<>(15.0,4.0),
std::mt19937());
std::vector<int> output(32);
for (int i = 0; i<400; ++i)
++output[rand()];
for (int i = 0; i<output.size(); ++i)
std::cout << i << '\t' << std::string(output[i],'*') << '\n';
}
0
1
2 *
3 **
4 **
5 **
6 ***
7 ***
8 ******
9 ***************
10 **************************
11 ******************
12 ************************************************
13 ******************************************
14 ****************************************
15 *******************************
16 ***************************************
17 **************************************
18 *************************
19 *****************
20 ************
21 ************
22 *****
23 *******
24 ***
25 **
26
27 *
28
29
30
31
Upvotes: 3
Reputation: 150987
Well, I can't speak about C++, but Python uses the Mersenne Twister. So there's no need to implement your own in Python. Also, Python only uses the system time as a seed if there's no other source of randomness; this is a system-dependent issue. See also the os.urandom
docs about this.
It's fun to write your own, though. The pseudocode on the MT Wikipedia page is clear and easy-to-implement.
Of course the usual caveats apply. This is not a cryptographic random number generator. Not all permutations of a largish list can be generated by random.shuffle
, and so on. But for the uses you specify, it's likely that the Mersenne Twister is fine.
Upvotes: 5
Reputation: 523304
Python's random.uniform()
is fine. Actually it already uses Mersenne-Twsiter.
However, you'd better avoid C and C++'s rand()
, since it often produce bad random numbers (See also What common algorithms are used for C's rand()?). Even worse, on Windows the RAND_MAX is only 0x7fff so you can't get more than 32768 distinct values. If you could use C++11, check the new <random>
library which contains many random number generators, including MT-19937. Otherwise, you could still use Boost.Random.
Seeding a random number generator with time is fine, as long as (1) you're not working with serious crypotography (you shouldn't use Mersenne-Twsiter in crypotography anyway), and (2) you can guarantee that it is impossible to have two seeds with the same time value, which will cause the same sequence be generated.
Upvotes: 1
Reputation: 490148
At least in C++, rand
is sometimes rather poor quality, so code should rarely use it for anything except things like rolling dice or shuffling cards in children's games. In C++ 11, however, a set of random number generator classes of good quality have been added, so you should generally use them by preference.
Seeding based on time
can work fine under some circumstances, but not if you want to make it difficult for somebody else to duplicate the same series of numbers (e.g., if you're generating nonces for encryption). Normally, you want to seed only once at the beginning of the program, at least in a single-threaded program. With multithreading, you frequently want a separate seed for each thread, in which case you need each one to start out unique to prevent generating the same sequences in all threads.
Upvotes: 1