rand() between 0 and 1

C++Random

C++ Problem Overview


So the following code makes 0 < r < 1

r = ((double) rand() / (RAND_MAX))

Why does having r = ((double) rand() / (RAND_MAX + 1)) make -1 < r < 0?

Shouldn't adding one to RAND_MAX make 1 < r < 2?

Edit: I was getting a warning: integer overflow in expression

on that line, so that might be the problem. I just did cout << r << endl and it definitely gives me values between -1 and 0

C++ Solutions


Solution 1 - C++

This is entirely implementation specific, but it appears that in the C++ environment you're working in, RAND_MAX is equal to INT_MAX.

Because of this, RAND_MAX + 1 exhibits undefined (overflow) behavior, and becomes INT_MIN. While your initial statement was dividing (random # between 0 and INT_MAX)/(INT_MAX) and generating a value 0 <= r < 1, now it's dividing (random # between 0 and INT_MAX)/(INT_MIN), generating a value -1 < r <= 0

In order to generate a random number 1 <= r < 2, you would want

r = ((double) rand() / (RAND_MAX)) + 1

Solution 2 - C++

rand() / double(RAND_MAX) generates a floating-point random number between 0 (inclusive) and 1 (inclusive), but it's not a good way for the following reasons (because RAND_MAX is usually 32767):

  1. The number of different random numbers that can be generated is too small: 32768. If you need more different random numbers, you need a different way (a code example is given below)
  2. The generated numbers are too coarse-grained: you can get 1/32768, 2/32768, 3/32768, but never anything in between.
  3. Limited states of random number generator engine: after generating RAND_MAX random numbers, implementations usually start to repeat the same sequence of random numbers.

Due to the above limitations of rand(), a better choice for generation of random numbers between 0 (inclusive) and 1 (exclusive) would be the following snippet (similar to the example at http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution ):

#include <iostream>
#include <random>
#include <chrono>

int main()
{
	std::mt19937_64 rng;
	// initialize the random number generator with time-dependent seed
	uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
	std::seed_seq ss{uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed>>32)};
	rng.seed(ss);
	// initialize a uniform distribution between 0 and 1
	std::uniform_real_distribution<double> unif(0, 1);
	// ready to generate random numbers
	const int nSimulations = 10;
	for (int i = 0; i < nSimulations; i++)
	{
		double currentRandomNumber = unif(rng);
		std::cout << currentRandomNumber << std::endl;
	}
	return 0;
}

This is easy to modify to generate random numbers between 1 (inclusive) and 2 (exclusive) by replacing unif(0, 1) with unif(1, 2).

Solution 3 - C++

No, because RAND_MAX is typically expanded to MAX_INT. So adding one (apparently) puts it at MIN_INT (although it should be undefined behavior as I'm told), hence the reversal of sign.

To get what you want you will need to move the +1 outside the computation:

r = ((double) rand() / (RAND_MAX)) + 1;

Solution 4 - C++

It doesn't. It makes 0 <= r < 1, but your original is 0 <= r <= 1.

Note that this can lead to undefined behavior if RAND_MAX + 1 overflows.

Solution 5 - C++

My guess is that RAND_MAX is equal to INT_MAX and so you're overflowing it to a negative.

Just do this:

r = ((double) rand() / (RAND_MAX)) + 1;

Or even better, use C++11's random number generators.

Solution 6 - C++

This is the right way:

double randd() {
  return (double)rand() / ((double)RAND_MAX + 1);
}

or

double randd() {
  return (double)rand() / (RAND_MAX + 1.0);
}

Solution 7 - C++

this->value = rand() % (this->max + 1);

Seems to work fine between 0 and 1++.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCyberShotView Question on Stackoverflow
Solution 1 - C++Sam DeHaanView Answer on Stackoverflow
Solution 2 - C++Serge RogatchView Answer on Stackoverflow
Solution 3 - C++TudorView Answer on Stackoverflow
Solution 4 - C++Luchian GrigoreView Answer on Stackoverflow
Solution 5 - C++PubbyView Answer on Stackoverflow
Solution 6 - C++KIM TaegyoonView Answer on Stackoverflow
Solution 7 - C++ValtsuhView Answer on Stackoverflow