From: buers AT gmx DOT de (Dieter Buerssner) Newsgroups: comp.os.msdos.djgpp Subject: Re: Random numbers Date: 25 May 2000 11:27:09 GMT Lines: 61 Message-ID: <8gja2u.3vvquht.0@buerssner-17104.user.cis.dfn.de> References: <392CB951 DOT 34B432E6 AT chemistry DOT uq DOT edu DOT au> NNTP-Posting-Host: pec-1-228.tnt1.s2.uunet.de (149.225.1.228) Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Trace: fu-berlin.de 959254029 1514814 149.225.1.228 (16 [17104]) X-Posting-Agent: Hamster/1.3.13.0 User-Agent: Xnews/03.02.04 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com Chris Miller wrote: >Ideally, I am attempting to generate a random integer between 0 and >1,000,000. If you want to be portable, you have to be very careful with such a large range. RAND_MAX can be as small as 32767 (and often is). Depending on your problem, I can suggest two solutions. If you do not need "high-quality" random numbers, you can shift together two return values of rand(). Of course, much care has to be taken, because RAND_MAX+1 is not guaranteed to be a power of two. The other solution is to write your own PRNG or load it from the net. (You could do a web-search for Mersenne Twister.) A not too bad and portable PRNG is the following, originally suggested by George Marsaglia. It will return pseudo random numbers between 0 and 0xffffffffUL (both inclusive). static unsigned long zs = 1234567UL; static unsigned long ws = 7654321UL; /* Combine two multiply with carry PRNGs */ unsigned long mwc1616(void) { unsigned long t = zs; zs = 30903*(t&0xffffUL)+(t>>16); t = ws; ws = 18000*(t&0xffffUL)+(t>>16); return ((ws<<16)&0xffffffffUL) + (zs&0xffffUL); } void seed_mwc1616(unsigned long s) { s &= 0xffffffffUL; /* Mask for portablity to 64bit long */ if (s == 0) s = 1234567UL; zs = s; ws = 7654321UL; } Then your random number between 0 an 1,000,000 (inclusive) would be unsigned long r = (unsigned long)((mwc1616()/4.294967296e9) * 1000001.0); /* or mwc1616() * 2.3283064365386962890625e-10 * 1000001.0 */ /* or mwc1616() * 2.3283087648451328277587890625e-4 */ Note, that this method won't generalize to a larger range. Then more sophisticated methods would be needed. For your special problem, the method will return some numbers with a probability of floor(2^32/1000001)/2^32 = 0.9997748e-6 and the other numbers with a probability of ceil(2^32/1000001)/2^32 = 1.0000076e-6. This small difference should be ok for many purposes. In general, the larger the range, the larger will be the difference in the probabilities (unless the range is a power of two). Of course, when you are interested in DJGPP only, you can write int r = (int)(rand() * 1000001.0)/(RAND_MAX+1.0); -- Regards, Dieter Buerssner