Mark Anderson
Mark Anderson

Reputation: 2459

How can I transform a random integer to a uniform real [0,1[ distribution

On Wikipedia, I found the following random number generator:

#include <stdint.h>

/* The state must be seeded so that it is not everywhere zero. */

uint64_t s[ 2 ];

uint64_t next(void) { 
    uint64_t s1 = s[ 0 ];
    const uint64_t s0 = s[ 1 ];
    s[ 0 ] = s0;
    s1 ^= s1 << 23;
    return ( s[ 1 ] = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) ) ) + s0;
}

Now, when implemented, (using a random seed for s[0] and s1), this works nicely, but outputs numbers like:

2318509732609079156, 5455176535758408500, 14446583927462861784, 3420274542024626201, etc.

My question now is: How can I transform these numbers to a uniform real distribution [0,1[, i.e. with 0 included and 1 excluded?

Upvotes: 1

Views: 1114

Answers (2)

anderas
anderas

Reputation: 5844

Assuming that you want a double result, simply cast the result of your random generator to double and divide by the maximum value (i.e. 2^64):

double result = next() / (double) std::numeric_limits<uint64_t>::max();

Note that some precision might be lost when converting to 64bit real values, so the values might not be exactly uniformly distributed. If this matters for your application, you shouldn't use this code...

edit: Sorry, this could also result in the value 1. A simple workaround would be to repeat this until the value is not 1, or making sure that next() never returns std::numeric_limits<uint64_t>::max().

edit: Even simpler, as inspired by 40two's answer: Call std::uniform_real_distribution with your random generator:

std::uniform_real_distribution<double> distribution(0.0,1.0);
double random_number_in_01 = distribution(next);

Upvotes: 1

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

In C++11 there's a way to produce uniformly distributed numbers over an interval with std::uniform_real_distribution:

// uniform_real_distribution
#include <iostream>
#include <random>

int main()
{
  std::default_random_engine generator;
  std::uniform_real_distribution<double> distribution(0.0,1.0);
  double random_number_in_01 = distribution(generator);

  return 0;
} 

Upvotes: 3

Related Questions