Archived

This topic is now archived and is closed to further replies.

ktuluorion

Generating large random #'s

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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 people

short type; //type of planet

short wealth; //scale of 1 to 10; 1 being poorest, 10 being highest

long supply[10]; //how much they have of each product

long production[10]; //how much they produce of each product

long 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);
}


Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Guest 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...

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites