How do I generate a random intager in C++?

Also could I set the number to be in a certain range, such as between 0 and 25.

Printable View

- 05-23-2004New001Random Number
How do I generate a random intager in C++?

Also could I set the number to be in a certain range, such as between 0 and 25. - 05-23-2004Ken Fitlike
faq.

- 05-24-2004big146Random Numbers
Hi there,

#include<cstdlilb>

int random;

random = 1 + rand() % 25;

will generate random numbers in the range of 1 to 25.

But these will be fairly predictable numbers.

#include <ctime>

#include <cstdlib>

srand(time(0) ); //uses clock to seed the random number

dice1 = 1 + rand() % 6;

more random- uses clock seconds to seed.

Hope this helps. - 05-24-2004New001
Ok thanks

- 05-25-2004Russell
A better seed:

Code:`1 #include <iostream>`

2

3 extern "C" {

4 #include <time.h>

5 }

6

7 int main(int argc,char* argv[])

8 {

9 struct timespec seed;

10 for (int i=0;i<=10;++i) {

11 clock_gettime(CLOCK_REALTIME,&seed);

12 srand(seed.tv_sec+seed.tv_nsec);

13 std::cout<<rand()%10000<<std::endl;

14 }

15

16 return 0;

17 }

- 05-25-2004Prelude
>struct timespec seed;

>clock_gettime(CLOCK_REALTIME,&seed);

Neither of these are standard. A good, portable method still uses the current time, but instead uses a pseudo-hash of the bytes in a time_t value:

Code:`/*`

Based off of Ben Pfaff's implementation that was based off

of Lawrence Kirby's implementation. :-)

*/

#include <cstddef>

#include <ctime>

#include <limits>

unsigned

time_seed()

{

time_t timeval; /* Current time. */

unsigned char *ptr; /* Type punned pointed into timeval. */

unsigned seed; /* Generated seed. */

size_t i;

timeval = std::time(0);

ptr = reinterpret_cast<unsigned char *>(&timeval);

seed = 0;

for (i = 0; i < sizeof timeval; i++) {

seed = seed * (std::numeric_limits<unsigned char>::max() + 2U) + ptr[i];

}

return seed;

}

Code:`std::srand(time_seed());`

Using the low order bits of a random number may not result in a good distribution. I've seen long strings of repeating numbers when using modulus with rand. A better way would be to divide by RAND_MAX. Here's a nifty function to do that:

Code:`#include <cstdlib>`

#include <iostream>

double

random()

{

return static_cast<double>(std::rand()) / RAND_MAX;

}

int

main()

{

std::srand(time_seed());

for (int i = 0; i < 10; i++) {

std::cout<< static_cast<int>(random() * 10) <<std::endl;

}

}

- 05-25-2004elad
Wait a minute. Assume, for sake of simplicity, that RAND_MAX is 10,000 (I know that that isn't the real value of RAND_MAX) and that rand() returns a value between 0 and RAND_MAX. Division of the return value by RAND_MAX will result in values ranging from 1 to 0.0001. The number of times 0 appears in the first placeholder to the right of the decimal has to be greater than the number of times any other digit appears in that spot given that 0 is in that spot for all numbers less than 0.1, which is well over half of all the possible values obtainable by division of RAND_MAX. Multiplication of that value by 10 will promote the first digit to the right of the decimal to integer status, meaning the probability of having 0 as the final result of (rand()/RAND_MAX) * 10 has to be over 50%, too. Therefore the chance of having a string of zeros as a result of that process should be significantly higher than a string of any given digit using a modulus with a constant (other than 1). Or am I missing something here? (Wouldn't be the first time.)

- 05-25-2004Thantos
1) The range of numbers is 0 to 1 when using the divison method.

2) Every RAND_MAX I've seen is odd. I'm fairly confident this is by design to avoid problems such as above. - 05-25-2004elad
But that begs the argument (argument here being my side of the debate, not speaking in anger) as posed.

- 05-25-2004Thantos
Well really it could be a lot less than .0001 since you are storing it into a double. In set notation it would look like [0,1].

If RAND_MAX was 10000 then yes you could have problems. However that is completely outside the bounds of what is. Values I've seen used for RAND_MAX:

16383

32767

65535

2147483647

Notice a pattern here? - 05-25-2004swoopy
>for all numbers less than 0.1, which is well over half of all the possible values obtainable by division of RAND_MAX.

Why do you say well over half? I would say 1/10, or 10%. - 05-25-2004RussellQuote:

Originally Posted by**Prelude**

Thanks for that extra information. =) - 05-26-2004elad
swoopy---Thanks for getting me to think through the problem from a different angle and therefore helping me see the error of my initial logic. You are correct. I am wrong.

If rand() returns a value from 0 to RAND_MAX and RAND_MAX is defined as 10000 then you can generate a table as follows:

0/10000 = 0

1/10000 = 0.0001

10/10000 = 0.001

100/10000 = 0.01

1000/10000 = 0.1

2000/10000 = 0.2

3000/10000 = 0.3

Therefore there are 1000 possible values of rand(), 0 to 999, that will give results less than 0.1, or 10% of all possible values of rand(). Likewise there are 1000 possible values of rand(), 1000 to 1999, that will give end results 0.1 to < 0.2 which is 10%, and similar for 0.2 to 0.3, etc. The same logic should hold for any value assigned to RAND_MAX. Now Preludes code makes sense.

Thank you. - 05-26-2004swoopy
Elad, both you and Prelude are much more logical thinkers than myself. For the part of your quote I posted, I thought maybe I had interpreted it wrong, so wanted some clarification from you. It's fun to learn new things from threads of this nature.

It's understandable why dividing by RAND_MAX gives an even distribution, but it's unclear why modulus doesn't. However since Prelude has explained this before, I was aware modulus was to be avoided. - 05-27-2004elad
swoopy, I'm not sure why Preludes indicates that rand()/RAND_MAX is less likely to give a string of equal values on repeated values than rand()/modulus, either; but it clearly isn't the reason I initially came up with, as you pointed out. Maybe the problem is I'm misinterpretting what Prelude wrote in the first place.