2

I am currently implementing a random number generator in Qt5.3 as part of genetic algorithm experiments. I have tried several methods but the best seems to be:

  // Seed the random generator with current time
  QTime time = QTime::currentTime();
  qsrand((uint)time.msec());

And then this funtion to generate the random numbers:

int MainWindow::getRandomNo(int low, int high)
{
    return qrand() % ((high + 1) - low) + low;
}

Because of the nature of these experiments, the random nature of these numbers is important. Is there a way to improve the quality of the random number samples? Upon statistical analysis, the Qt random number generator exhibits typical patterns that are found in older systems of random number generation.

The method used above relies on the current time as a seed for the number generator. Is there a way to improve the seed so that the random sequences are less prone to patterns? I would be extremely grateful for any help.

Adam893
  • 143
  • 1
  • 3
  • 16
  • 3
    Any reason not to use `` ? It's much more robust. – MSalters Oct 03 '14 at 16:54
  • It seems to suffer from the same pattern issues - almost predictable given a large enough sample size. – Adam893 Oct 03 '14 at 16:56
  • 2
    Every PRNG is predictable with a "large enough" sample size. But "large enough" is far from possible with good algorithms. Did you even look at the available ones? http://www.cplusplus.com/reference/random/ – deviantfan Oct 03 '14 at 17:06
  • This particular application is a simulation of the evolutionary process and as such will perform better, the more random the input. The random number generators you have mentioned are fantastic - but this is the problem, they are too good. The random sequences generated are all far too evenly spread to be of any use. What is needed is a system that can generate a true random sequence. The only thing that even came close to this was a hardware random number generator. So far the best I have found is the Qt one in my question, using the clock as a seed. – Adam893 Oct 03 '14 at 17:16
  • 2
    There is no such thing as a RNG which is "too good". Mersenne Twister will provide you any sequence of numbers with (almost) the same probability. Even a sequence such as 0 - 0 - 0 - 0 - 0 – B. Decoster Oct 03 '14 at 17:42
  • @Adam893: "far too evenly spread" is a property of "true random sequence". Or do you think "true random sequence" must have some pattern in it? – Siyuan Ren Oct 04 '14 at 09:29
  • I suspect that you need a non-uniform distribution, and that too is provided by ``. – MSalters Oct 04 '14 at 16:54
  • Many thanks for all responses. I understand the confusion over what I'm asking for, its difficult to convey the exact problem without some background knowledge of GAs! – Adam893 Oct 07 '14 at 15:49

3 Answers3

2

Use MT.

You can get an implementation here:

I ran into the same problem years ago in a delphi software, and switching to MT sovled my problem. But check the list in the boost docu for further detailed information about the differences between RNG algorithms.

Simon Warta
  • 10,850
  • 5
  • 40
  • 78
  • 2
    You're missing the most obvious place to look: ``. You don't need an extra library. – MSalters Oct 04 '14 at 16:55
  • I'm relieved to find someone who understands the issue! Thanks for the MT hint, it has made a remarkable difference. – Adam893 Oct 07 '14 at 15:50
  • 3
    @Adam893: Since you asked, everyone has pointed you to the header. An voila, there a MT implmentation. But back then, you were saying it´s "too good"... ? – deviantfan Oct 08 '14 at 12:38
1

Adjusting your seed won't really effect the quality of the numbers generated, just the particular order of the numbers generated. You will need to use a better algorithm to generate your random numbers.

In addition, the way you are using the generated numbers is slightly biased. With your getRandomNo function, there will be a slight bias towards smaller numbers. For example if qrand returns a value in the range 0..2^32-1, and you have low=0 and high=2^32-2, then using % as you do, will mean that 0 will be returned (approximately) twice as often as any other number.

An improvement would be to try something like this:

Let n be a positive integer where you want a random integer in the range 0..n-1, let m be the smallest power of 2 greater than or equal to n.

unsigned int myrand( unsigned int n, unsigned int m )
{
    unsigned int i = qrand() % m; /* or (qrand() & (m-1)) */
    while ( i >= n )
    {
        i = qrand() % m;
    }

    return i;
}

This will be slower, but the expected number of iterations is 2. Also, if you are using the same range multiple times, you can pre-compute m.

dohashi
  • 1,771
  • 8
  • 12
1

an amendment to dohashi's answer can be to take m as the first prime number greater than or equal to n

Community
  • 1
  • 1
H.B
  • 21
  • 2