Generating large random #'s

Started by
9 comments, last by ktuluorion 21 years, 6 months ago
Can anyone help me out? I need to generate larger random #''s than the rand() function will spit out. I''m using Microsoft Visual C++ 6.0. Any info would be appreciated. #''s will need to be in the millions, perhaps billions.
[Piebert Entertainment] [Ask The All-Knowing Oracle A Question]------------------------------------------------------------GDSFUBY GameDev Society For UnBanning YodaTheCodaIf you want to see yoda unbanned then put this in your sig ------------------------------------------------------------DAIAGA Dave Astle is a God Association. To join, put this in your sig!Founder and High Priest of DAIAGA[edited by - YodaTheCoda on December 10, 2003 1:57:54 PM]
Advertisement
I think that rand() returns an int....

long big = rand() | (rand() << 32);

That would put the first rand on the right end of the long and the second rand on the left.
only shift it up 16 bits, by the way.

anything << 32 <--- zero.


Also, rand() in Visual C returns a 15 bit number, not 16.


so, it would probably be better to do this:


    unsigned long int BigRand(){    return rand() | (rand() << 15) | (rand() << 30);}    


EDIT
32 bit compilers will truncate 30 bits off the last number.
So it is optional, but remember, a 32 bit number can hold 4x as many numbers as a 30 bit number.

[edited by - Mithrandir on October 2, 2002 10:37:07 AM]
This is my signature. There are many like it, but this one is mine. My signature is my best friend. It is my life. I must master it as I must master my life. My signature, without me, is useless. Without my signature, I am useless.
For some reason I am getting very similar values. If anyone can help let me know:


  #include <stdlib.h>#include <stdio.h>#include <time.h>#include <iostream.h>//products list://1. Food//2. Water//3. Steel//4. Fuel//5. Gems//6. //7.//8.//9.//10.const double basecost[10]={1,.3,1.5,1,3,1,1,1,1,1};struct pricestruct  //a return which says how much merchants will                     //sell for{int buyhigh;int buylow;int sellhigh;int selllow;};struct shipstruct{	short type;      	int holds[10];  //how much of each product in holds    int maxholds;	long fighters;};struct playerstruct{shipstruct ship;  //the player has a ship.};struct planetstruct{long population;  //how many peopleshort type;    //type of planetshort wealth;  //scale of 1 to 10;  1 being poorest, 10 being highestlong supply[10];  //how much they have of each productlong production[10]; //how much they produce of each productlong need[10]; //how much they need of each product};int determinetargetprice()  //will send back how much something will                            //buy/sell for{    return 0;}void generateplanet(planetstruct &planet) //randomly create a planet{		planet.population= rand() | ((long)rand << 15) | ((long)rand << 30);;    			planet.type=(rand()%10);}int main(){pricestruct price;planetstruct planet;	srand( (unsigned int)time( (time_t *)NULL ) );    	for (int i=0;i<4;i++){	generateplanet(planet);cout<<"Population: "<<planet.population<<endl;cout<<"Planet Type: "<<planet.type<<endl;	}return(0);}  
[Piebert Entertainment] [Ask The All-Knowing Oracle A Question]------------------------------------------------------------GDSFUBY GameDev Society For UnBanning YodaTheCodaIf you want to see yoda unbanned then put this in your sig ------------------------------------------------------------DAIAGA Dave Astle is a God Association. To join, put this in your sig!Founder and High Priest of DAIAGA[edited by - YodaTheCoda on December 10, 2003 1:57:54 PM]
Go here or here
You forgot to put the () after the second two calls to rand. This will give you the address of the rand function shifted left, which should give you large but very similar numbers.

If you're OK just want 30 bits of randomness you're probably better off with just the two calls--that last call of rand is only going to get you 2 more bits since the unsigned long is 32 bits total.

Also, never use modulo (%) with rand ().
See this link for an extended discussion on why.

For MSVC, I suggest:
LIMIT * rand () / (RAND_MAX + 1);
This won't work with gnu, but it's hella-fast for MSVC.

Your new function:

  void generateplanet(planetstruct &planet) //randomly create a planet{  planet.population= rand() | (rand () << 15); // 30 bit max  planet.type= 10 * rand () / (RAND_MAX + 1);}  


[edited by - Stoffel on October 2, 2002 2:07:22 AM]
To adapt Stoffel''s answer, you can use rand again to randomise the last 2 bits, or even make a random 64-bit integer (the code is Win32 only, I don''t know a standard way of doing this).

unsigned long int RandInt (void){    return rand () | (rand () << 15) | ((rand () & 3) << 30);}LARGE_INTEGER RandLargeInt (void){    LARGE_INTEGER li;    li.LowPart = (DWORD) RandInt ();    li.HighPart = (LONG) RandInt ();    return li;} 


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions
quote:Original post by siaspete

unsigned long int RandInt (void){    return rand () | (rand () << 15) | ((rand () & 3) << 30);} 


You don''t even really need to logically-and it; the compiler will automatically truncate it when you shift it up 30. See my original post in this thread.
This is my signature. There are many like it, but this one is mine. My signature is my best friend. It is my life. I must master it as I must master my life. My signature, without me, is useless. Without my signature, I am useless.
A few points

1 - Calling rand() twice (or more) doesn''t actually give very good randomness. rand() uses the first call to seed the second, so for a given initial seed you will always get the same sequence of numbers. So you''re not actually picking a number from the complete set of numbers from 0-2^32-1. You''re actually only getting a subset of RAND_MAX size. Of course, for what you''re doing it may be fine except that...

2 - You say that you get similar numbers with your code. If you''re trying to get planet populations you may be wanting some planets to be big(billions), and some to be small(millions). With a straightforward random function going from 0-2^32, 75% of your numbers will be in the trillions. 97.5% will be greater than 100 billion. Only 1 in 4 million will be less than 10 million.

3 - Your function is coming up with a very precise number - do you really want a population of 3,451,983,901? Or do you want a population of 3.5 billion?

If it were me, I''d probably do something simple like:
Pick two random numbers. One, I''ll call it x, from 10-99, and one, y, from 6-10. Then my population would be x/10 * 10^y.
Ex: x=35, y=7, pop=35 million.
quote:Original post by Anonymous Poster
A few points

1 - Calling rand() twice (or more) doesn''t actually give very good randomness. rand() uses the first call to seed the second, so for a given initial seed you will always get the same sequence of numbers. So you''re not actually picking a number from the complete set of numbers from 0-2^32-1. You''re actually only getting a subset of RAND_MAX size. Of course, for what you''re doing it may be fine except that...

Untrue in MSVC. rand () does not use the output of rand () to seed itself. Rather, the seed is kept internally and is much larger than the number actually output by rand (). This is easy enough to verify:

  #include <stdlib.h>#include <iostream>using namespace std;int main (){   int lastRand = rand ();   int hits = 0;   while (hits < 100)   {      int thisRand = rand ();      if (0 == lastRand)      {         cout << thisRand << ", ";         ++hits;      }      lastRand = thisRand;   }   return 0;}  

This will show the number generated by rand () after rand () generates a 0. The pattern will eventually repeat, but not for a while. It''s certainly not the same number every time, as you suggest.

quote:
2 - You say that you get similar numbers with your code. If you''re trying to get planet populations you may be wanting some planets to be big(billions), and some to be small(millions). With a straightforward random function going from 0-2^32, 75% of your numbers will be in the trillions. 97.5% will be greater than 100 billion. Only 1 in 4 million will be less than 10 million.

True. A better solution might be to multiply two rand numbers, which will give you a exponential distribution. But that''s only if that''s what the original poster wanted. For the real reason he was getting similar numbers, see my original post.

This topic is closed to new replies.

Advertisement