3

I need to generate random numbers between two specified numbers in a loop with a uniform distribution. I am using the random library of C++11.

My problem is that I keep getting the same number in the loop. It is required that the number generated on every loop pass be different. Code below:

#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <random>
using namespace std;

double randnum (double a, double b)
{
  std::default_random_engine generator;
  std::uniform_real_distribution<double> distribution (a,b);
  double num=distribution(generator);

  return num;
}


int main()
{
    int np=100;

    double umin =0;
    double umax=0.5;
    double u[np];

    for (int i=0;i<np;i++)
    {
        u[i]=randnum(umin,umax);
        cout<<u[i]<<endl;
    }    
}

Please help. Any advice on generating random number by any alternative means is welcome, but it must have a uniform distribution.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
nash.ouroboro
  • 83
  • 1
  • 6
  • 7
    Don't construct an RNG on every function call. Construct it once. – T.C. Sep 14 '15 at 22:57
  • You're not seeding your `generator` properly. Try using [`random_device`](http://en.cppreference.com/w/cpp/numeric/random/random_device) for doing so, but be warned, see [here](http://stackoverflow.com/a/18880689/2851815) – набиячлэвэли Sep 14 '15 at 22:58
  • Thank you for the advice. Both solutions work. Although generating a static function feels the most convenient (as suggested in the answer). I understand that the numbers generated will be pseudo random, but it will solve the purpose of my code. – nash.ouroboro Sep 16 '15 at 17:47

2 Answers2

6

The random number engines in the Standard Library are pseudo-random, i.e. deterministic in how their internal state is initialized and mutated. This means that each function call will get a fresh new generator that will continue to give the same number over and over again.

Just make the generator a static function variable so that its state can evolve over different function calls.

#include <iostream>
#include <random>
using namespace std;

double randnum (double a, double b)
{
  static std::default_random_engine generator;
  std::uniform_real_distribution<double> distribution (a,b);
  return distribution(generator);
}

int main()
{
    const int np=100;

    double umin =0;
    double umax=0.5;
    double u[np];

    for (int i=0;i<np;i++)
    {
        u[i]=randnum(umin,umax);
        cout<<u[i]<<endl;
    }    
}

Live Example.

Note, you will get the same sequence of numbers for each run of your compiled program. To get more random behavior across program invocations, you can use e.g. std::random_device.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
1

Wanted to add to the 1st answer: Using static function will generate different numbers in the loop but would generate the same set of random numbers on every run. I avoided this by using time as seed:

#include <iostream>
#include <random>
#include <chrono>
using namespace std;

double randnum (double a, double b)
{
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  static std::default_random_engine generator (seed);
  //static std::default_random_engine generator;
  std::uniform_real_distribution<double> distribution (a,b);
  return distribution(generator);
}

int main()
{
    const int np=100;

    double umin =0;
    double umax=0.5;
    double u[np];

    for (int i=0;i<np;i++)
    {
        u[i]=randnum(umin,umax);
        cout<<u[i]<<endl;
    }    
}
nash.ouroboro
  • 83
  • 1
  • 6
  • Note: using time as a seed is great for simulations and the like, but don't use it as a seed for cryptographic applications, as that's too easily brute-forced. Also, it may be a good idea to log the used value in case you ever need to repeat a particular run (for debugging, perhaps). Again, not if you're doing cryptography! – Toby Speight Sep 16 '15 at 18:35
  • Thanks for the tip. I am using it for fluid dynamics simulation and therefore the time seed, or any for that matter, should be good for my case. – nash.ouroboro Sep 22 '15 at 20:35