2

I have a function that im trying to produce random numbers between 18 and 5

int randomAge() {
  int random;
  std::random_device rd;
  static std::default_random_engine generator(rd()); //produce a static random engine
  std::normal_distribution<double> distribution(18, 52);  //random age between 18 and 52
  random = distribution(generator);
  return random;
}

However I am recieving negative numbers and even numbers that are higher than 52. How can I fix this so it produces numbers between 18 and 52?

davidlingg2000
  • 107
  • 1
  • 5
  • 4
    You want a uniform distribution, not a normal distribution. Google it – JHBonarius Oct 26 '20 at 07:13
  • `std::normal_distribution distribution(18, 52);` is a normal distribution with a mean value of 18 and standard deviation of 52. Negative numbers are to be expected here. – Lukas-T Oct 26 '20 at 07:17
  • Very simplified, a uniform distribution with those parameters is centered around 18, and most (68%) of the numbers it produce are in the (18-52; 18+52) = (-34; 70) range. – Frodyne Oct 26 '20 at 07:23
  • 1
    Sidenote: Your `randomAge()` function will seed a new PRNG every time it's called. You should normally only see one PRNG (per thread) once and use it for the rest of the program's execution. – Ted Lyngmo Oct 26 '20 at 07:52

2 Answers2

6

You're using std::normal_distribution which generates random numbers according to the Normal (or Gaussian) random number distribution. You're using this constructor:

explicit normal_distribution( RealType mean, RealType stddev = 1.0 );

What you want is std::uniform_real_distribution. See the reference:

Produces random floating-point values i, uniformly distributed on the interval [a, b)

Do note that your engine and distribution must be thread_local (or static) and the random device can be a temporary. Otherwise your results are not uniformly distributed. You should also consider getting a random integer instead of double since the return type is int anyway:

#include <random>

int randomAge() {
  thread_local std::mt19937 engine{ std::random_device{}() };
  thread_local std::uniform_int_distribution<int> distribution{ 18, 52 };
  return distribution(engine);
}

Related:

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
3

std::normal_distribution<T>(mean,sd)(<-clickable link) produces a normal distribution(<-clickable link) with a mean (middle point) of mean and a standard deviation ('spread') of sd.

If you want a uniform spread between two numbers, you need to use a std::uniform_real_distribution(<-clickable link).

JHBonarius
  • 10,824
  • 3
  • 22
  • 41