Uniform random number generator in C ++

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

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

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

      

+3


source to share


5 answers


You must initialize the seed engine, otherwise the default seed will 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 periodic in some way, which you would not expect from a non-deterministic number. For example, it std::mt19937

has a period of 2 19937 -1 iterations. True randomness is difficult to achieve, as you will need to keep an eye on things that don't seem deterministic (user input, atmospheric noise). See Jerry and Response Fingerprint .

If you don't want time based seeds you can use std::random_device

as shown in emsr answer . You can even use it std::random_device

as a generator that comes closest to true randomness using standard library methods.

+10


source


These are pseudo-random number generators. They can never produce truly random numbers. To do this, you usually need special equipment (for example, usually things like measuring noise in a thermal diode or radiation from a radioactive source).

To get sequences of differences from the pseudo-random generators in different runs, you usually seed the generator based on the current time.



This gives pretty predictable results (i.e. someone else can figure out which seed you were using quite easily. If you need to prevent this, most systems do provide some source of at least random numbers. On Linux, / dev / and in the Windows, CryptGenRandom

.

These latter are usually pretty slow, so you usually want to use them as a seed, rather than just extracting all your random numbers from them.

+7


source


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

Without external "random" input (for example, monitoring street noise), like a deterministic machine, the computer cannot generate truly random numbers: Generation of random numbers .

Since most of us don't have the money and experience to use dedicated hardware to provide chaotic input, there are ways to utilize the somewhat unpredictable nature of your OS, task scheduler, process manager, and user inputs (like mouse movement) to create improved pseudo-randomness.

Unfortunately, I don't know enough about C ++ TR1 to know if it has the ability to do this.

Edit

As others have pointed out, you end up with different sequences of numbers (which end up repeating, so they're not truly random) by seeding your RNG with different inputs. Thus, you have two options for improving your generation:

Save your RNG periodically with some kind of chaotic input, or make your RNG's output unreliable depending on how your system is doing.

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

The latter can be achieved through poor concurrency practice: that is, setting many RNG threads / processes to compete in an "unsafe manner" to generate each subsequent random number (or numeric sequence). This implicitly adds chaos to the total amount of activity on your system, because every minute event will affect which stream output ends up being written and eventually read when a method like GetNext () is called. Below is a clear proof of concept in .NET 3.5. Note two things: 1) Even though the RNG is seeded with the same number every time, 24 identical lines are not created; 2) There is a noticeable impact on performance and an obvious increase in resource consumption,which is relevant when improving the generation of random numbers:

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 generation, this method will create an infallible, non-repeating sequence of "random" numbers. In such a scenario, knowledge of the initial state of the machine would be insufficient to predict the outcome.

+3


source


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 that will be used. Otherwise, an implementation MAY use one of its pseudo-random generators. In g ++, mt19937 is used as a fallback.

I'm pretty sure tr1 has this as well as bu, as others have pointed out that I think it is best to use the C ++ 11 std utilities at this point.

Ed

+3


source


Here is an example of seeding an 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';
}

      

Sowing with current times can be relatively predictable and probably not something to do. The above at least does not limit you to only one possible seed per second, which is very predictable.

If you want to strip 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);

      

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

Of course, you won't pick anything from mt19937 to match your "true random number" requirement, and I suspect you don't really need true randomness.

+2


source







All Articles