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.
This is a discussion on Random Number within the C++ Programming forums, part of the General Programming Boards category; How do I generate a random intager in C++? Also could I set the number to be in a certain ...
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.
faq.
CProgramming FAQ
Caution: this person may be a carrier of the misinformation virus.
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.
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 }
>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:
You would use it like this: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; }
>std::cout<<rand()%10000<<std::endl;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; } }
My best code is written with the delete key.
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.)
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.
But that begs the argument (argument here being my side of the debate, not speaking in anger) as posed.
Last edited by elad; 05-25-2004 at 11:11 AM.
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?
>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%.
No, I didn't think so.Originally Posted by Prelude
Thanks for that extra information. =)
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.
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.
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.