15

I want to be able to generate random values between 0.0 and 1.0

I've tried to use

std::default_random_engine generator;
std::uniform_real_distribution<float> distribution(0.0, 1.0);

float myrand = distribution(generator);

Generating random value in a loop gives me always these values:

0.000022

0.085032

0.601353

0.891611

0.967956

0.189690

0.514976

0.398008

0.262906

0.743512

0.089548

What can I do to really get random values? Doesn't seem that random if I always get the same ones.

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
user1185305
  • 875
  • 2
  • 15
  • 26
  • Looks pretty random to me. Where is the problem? – Grizzly Mar 17 '13 at 13:19
  • @Grizzly: ahem: "*Doesn't seem that random if I always get the same ones.*" – Nicol Bolas Mar 17 '13 at 13:20
  • @NicolBolas: You want it to give the same values. Because debugging non deterministic code is a pain. But it is still random. It is just pseudo random and you are always starting at the same place. You just need to alter the starting point. – Martin York Mar 17 '13 at 13:52
  • 2
    @LokiAstari: I'm pretty sure that, if he wanted deterministic results, he wouldn't be *asking for* non-deterministic results. – Nicol Bolas Mar 17 '13 at 13:56
  • @NicolBolas: He might be now. But when he is debugging he will want to make them deterministic. – Martin York Mar 17 '13 at 13:58
  • 1
    @LokiAstari: And, if that's a problem, then that is something he can deal with when the time comes. It doesn't change what his question is, nor does it *invalidate* it. – Nicol Bolas Mar 17 '13 at 14:00
  • @NicolBolas: No the question is fine. Just giving context to your comment. The numbers are random and explaining why they need to be consistent. There are answers below on how to solve that that is why this is a comment. – Martin York Mar 17 '13 at 14:06
  • @LokiAstari: It wasn't "my comment". It was *the question*, which I was quoting to Grizzly because he seem to have missed it. – Nicol Bolas Mar 17 '13 at 14:32

4 Answers4

21
// 1-st variant: using time() function for seed random distribution
std::default_random_engine generator(time(0));
std::uniform_real_distribution<double> distribution(first, last);
return distribution(generator);

If open multiple programs, with the same random number generator they will all output the same results, because they have the same value of seed which is time.

This issue solved by using random device, in the below code:

// 2-nd variant: 
std::uniform_real_distribution<double> distribution(first, last);
std::random_device rd;
std::default_random_engine generator(rd());
return distribution(generator);
Matteo Guarnerio
  • 720
  • 2
  • 9
  • 26
spin_eight
  • 3,925
  • 10
  • 39
  • 61
  • 1
    +1 for `random_device` - if you know it's available on the systems your program should run, I like this solution best. – us2012 Mar 17 '13 at 13:26
9

If you are referring to the fact that you get the same results for each execution of the program, that's because you need to provide a seed based on some naturally random value (e.g. some number input by the user, or the number of milliseconds elapsed since the computer was turned on, or since January 1, 1970, etc.):

#include <random>

std::default_random_engine generator;
generator.seed( /* ... */ );
//              ^^^^^^^^^    
//              Provide some naturally random value here

std::uniform_real_distribution<float> distribution(0.0, 1.0);

float myrand = distribution(generator);
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
1

I have found another good solution...

double Generate(const double from, const double to)
{
    std::random_device rd;

    return std::bind(
        std::uniform_real_distribution<>{from, to},
        std::default_random_engine{ rd() })();
}
smela
  • 89
  • 1
  • 8
  • std::random_device rd was already proposed two years ago [here](https://stackoverflow.com/a/15461224/754550) – miracle173 Apr 07 '18 at 17:38
  • 3
    Initialising a new `std::random_device` and `std::default_random_engine` each time seems excessive – Caleth Jan 23 '20 at 14:51
0

Modifying the nice solution above into a class to avoid constant instantiation of the distribution and generator.

#include <random>

using namespace std;

class RangeRandGenerator {
    uniform_real_distribution<double> dist;
    random_device rd;
    default_random_engine gen;
public:
    RangeRandGenerator( double from, double to ) :
        dist(from, to), gen(rd()) {}
   
    double get() {
        return dist(gen);
    }
};
larboyer
  • 119
  • 1
  • 3