Question

I am trying to produce true random number in c++ with C++ TR1. However, when run my program again, it produces same random numbers.The code is below.

I need true random number for each run as random as possible.

std::tr1::mt19937 eng;  
std::tr1::uniform_real<double> unif(0, 1);
unif(eng);
Was it helpful?

Solution

You have to initialize the engine with a seed, otherwise the default seed is going to be used:

eng.seed(static_cast<unsigned int >(time(NULL)));

However, true randomness is something you cannot achieve on a deterministic machine without additional input. Every pseudo-random number generator is periodical in some way, which is something you wouldn't expect from a non-deterministic number. For example std::mt19937 has a period of 219937-1 iterations. True randomness is hard to achieve, as you would have to monitor something that doesn't seem deterministic (user input, atmospheric noise). See Jerry's and Handprint's answer.

If you don't want a time based seed you can use std::random_device as seen in emsr's answer. You could even use std::random_device as generator, which is the closest you'll get to true randomness with standard library methods only.

OTHER TIPS

These are pseudo-random number generators. They can never produce truly random numbers. For that, you typically need special hardware (e.g., typically things like measuring noise in a thermal diode or radiation from radioactive source).

To get a difference sequences from pseudo-random generators in different runs, you typically seed the generator based on the current time.

That produces fairly predictable results though (i.e., somebody else can figure out the seed you used fairly easily. If you need to prevent that, most systems do provide some source of at least fairly random numbers. On Linux, /dev/random, and on Windows, CryptGenRandom.

Those latter tend to be fairly slow, though, so you usually want to use them as a seed, not just retrieve all your random numbers from them.

If you want true hardware random numbers then the standard library offers access to this through the random_device class:

I use it to seed another generator:

#include <random>
...
  std::mt19937_64 re;
  std::random_device rd;
  re.seed(rd());
...
  std::cout << re();

If your hardware has /dev/urandom or /dev/random then this will be used. Otherwise the implementation is free to use one of it's pseudorandom generators. On G++ mt19937 is used as a fallback.

I'm pretty sure tr1 has this as well bu as others noted I think it's best to use std C++11 utilities at this point.

Ed

This answer is a wiki. I'm working on a library and examples in .NET, feel free to add your own in any language...

Without external 'random' input (such as monitoring street noise), as a deterministic machine, a computer cannot generate truly random numbers: Random Number Generation.

Since most of us don't have the money and expertise to utilize the special equipment to provide chaotic input, there are ways to utitlize the somewhat unpredictable nature of your OS, task scheduler, process manager, and user inputs (e.g. mouse movement), to generate the improved pseudo-randomness.

Unfortunately, I do not know enough about C++ TR1 to know if it has the capability to do this.

Edit

As others have pointed out, you get different number sequences (which eventually repeat, so they aren't truly random), by seeding your RNG with different inputs. So you have two options in improving your generation:

Periodically reseed your RNG with some sort of chaotic input OR make the output of your RNG unreliable based on how your system operates.

The former can be accomplished by creating algorithms that explicitly produce seeds by examining the system environment. This may require setting up some event handlers, delegate functions, etc.

The latter can be accomplished by poor parallel computing practice: i.e. setting many RNG threads/processes to compete in an 'unsafe manner' to create each subsequent random number (or number sequence). This implicitly adds chaos from the sum total of activity on your system, because every minute event will have an impact on which thread's output ends up having being written and eventually read when a 'GetNext()' type method is called. Below is a crude proof of concept in .NET 3.5. Note two things: 1) Even though the RNG is seeded with the same number everytime, 24 identical rows are not created; 2) There is a noticeable hit on performance and obvious increase in resource consumption, which is a given when improving random number generation:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace RandomParallel
{
    class RandomParallel
    {
        static int[] _randomRepository;
        static Queue<int> _randomSource = new Queue<int>();
        static void Main(string[] args)
        {
            InitializeRepository(0, 1, 40);
            FillSource();
            for (int i = 0; i < 24; i++)
            {
                for (int j = 0; j < 40; j++)
                    Console.Write(GetNext() + " ");
                Console.WriteLine();
            }
            Console.ReadLine();
        }
        static void InitializeRepository(int min, int max, int size)
        {
            _randomRepository = new int[size];
            var rand = new Random(1024);
            for (int i = 0; i < size; i++)
                _randomRepository[i] = rand.Next(min, max + 1);
        }
        static void FillSource()
        {
            Thread[] threads = new Thread[Environment.ProcessorCount * 8];
            for (int j = 0; j < threads.Length; j++)
            {
                threads[j] = new Thread((myNum) =>
                    {
                        int i = (int)myNum * _randomRepository.Length / threads.Length;
                        int max = (((int)myNum + 1) * _randomRepository.Length /     threads.Length) - 1;
                        for (int k = i; k <= max; k++)
                        {
                            _randomSource.Enqueue(_randomRepository[k]);
                        }
                    });
                threads[j].Priority = ThreadPriority.Highest;
            }
            for (int k = 0; k < threads.Length; k++)
                threads[k].Start(k);
        }
        static int GetNext()
        {
            if (_randomSource.Count > 0)
                return _randomSource.Dequeue();
            else
            {
                FillSource();
                return _randomSource.Dequeue();
            }
        }
    }
}

As long as there is user(s) input/interaction during the generation, this technique will produce an uncrackable, non-repeating sequence of 'random' numbers. In such a scenario, knowing the initial state of the machine would be insufficient to predict the outcome.

Here's an example of seeding the engine (using C++11 instead of TR1)

#include <chrono>
#include <random>
#include <iostream>

int main() {
    std::mt19937 eng(std::chrono::high_resolution_clock::now()
                                          .time_since_epoch().count());
    std::uniform_real_distribution<> unif;
    std::cout << unif(eng) << '\n';
}

Seeding with the current time can be relatively predictable and is probably not something that should be done. The above at least does not limit you just to one possible seed per second, which is very predictable.

If you want to seed from something like /dev/random instead of the current time you can do:

std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);

(This depends on your standard library implementation. For example, libc++ uses /dev/urandom by default, but in VS11 random_device is deterministic)

Of course nothing you get out of mt19937 is going to meet your requirement of a "true random number", and I suspect that you don't really need true randomness.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top