www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/05/29/08:00:33

From: buers AT gmx DOT de (Dieter Buerssner)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Odp: Random numbers
Date: 29 May 2000 11:47:50 GMT
Lines: 85
Message-ID: <8gtsle.3vvrb0l.0@buerssner-17104.user.cis.dfn.de>
References: <392CB951 DOT 34B432E6 AT chemistry DOT uq DOT edu DOT au> <018801bfc877$2a916ba0$0100a8c0 AT ivan>
NNTP-Posting-Host: pec-106-63.tnt6.s2.uunet.de (149.225.106.63)
Mime-Version: 1.0
X-Trace: fu-berlin.de 959600870 2106670 149.225.106.63 (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

Grzegorz Patoła wrote:

>Chris Miller wrote:
>> If RAND_MAX is set to 100, then a call to rand() should return an
>> integer between 0 and 100. 
>
>You can try sth like this:
>
>int lotto;
>lotto = rand() % 100;

You shouldn't use this method. Eli already has pointed out the
DJGPP FAQ in this thread, where you can find an explaination,
why this method should be avoided.

The following small program shows the failure of this method.
Instead of 100, 32 is used. To find the failure, quite many
calls to DJGPP rand() are needed. Many other rand() implementations
would give up much earlier.

The program calculates many random numbers between 0 and 32 (exclusive),
and counts, how many times it found each number. The method you suggested
and the method suggested in the FAQ are used.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define NTRY (1UL<<26)
#define RANGE 32
#define EXPECTED ((double)NTRY/RANGE)

int main(void)
{
  static unsigned long count[RANGE], count2[RANGE];
  unsigned long i;
  int j;
  double s, s2, d, t, t2;

  srand(time(NULL));
  for (i = 0; i < NTRY; i++)
  {
    count[rand()%RANGE]++; /* %-Method */
    count2[(unsigned)((double)rand()*RANGE/(RAND_MAX+1.0))]++; /* FAQ */
  }
  printf("Expecting on average E=%f\n", EXPECTED);
  printf("  r fnd(mod)  (E-f)^2/E        sum fnd(div)  (E-f)^2/E        sum\n"
  s = s2 = 0.0;
  for (j=0; j<RANGE; j++)
  {
    d = EXPECTED - count[j];
    s += (t = d*d/EXPECTED);
    d = EXPECTED - count2[j];
    s2 += (t2 = d*d/EXPECTED);
    printf("%3d %8lu %10f %10f %8lu %10f %10f\n",
           j, count[j], t, s, count2[j], t2, s2);
  }
  printf("chi^2(mod) = %f chi^2(div) = %f expecting %.0f +/- %.2f mostly\n",
         s, s2, RANGE-1.0, 2.0*sqrt(RANGE-1.0));
  return 0;
}

The output I get is the following:

Expecting on average E=2097152.000000
  r fnd(mod)  (E-f)^2/E        sum fnd(div)  (E-f)^2/E        sum
  0  2097152   0.000000   0.000000  2094874   2.474443   2.474443
  1  2097152   0.000000   0.000000  2096110   0.517733   2.992176
[Many similar lines snipped]
 30  2097152   0.000000   0.000000  2095026   2.155245  27.993832
 31  2097152   0.000000   0.000000  2098501   0.867749  28.861581
chi^2(mod) = 0.000000 chi^2(div) = 28.861581 expecting 31 +/- 11.14 mostly

Only look at the fnd columns. With your method, you find each number
exactly the same number of times. And this is not at all random, this
is very predictable, and for a random process extremly unlikely.

The other columns are for a more stringent statistical analysis.
Roughly, the (E-f)^2/E column should show numbers not much larger
than 1.0. The sum of these numbers (called chisquare) should be around 
31 (the degrees of freedom of this problem). 

-- 
Regards, Dieter Buerssner

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019