michelbi@oregon.uoregon.edu (Michel Biedermann) (05/07/89)
How good (i.e. random) is the rand() function in MSC 5.1/QC 2.0? Press, Flannery, Teukolski, and Vetterling of "Numerical Recipies in C" fame caution the reader to be "very, very suspicious" of any system-supplied rand() function. Does anybody have any comments on Microsoft's rand() function? Thank you for the help. Michel Biedermann U. of Oregon ZENITH Student Rep.
desnoyer@Apple.COM (Peter Desnoyers) (05/09/89)
In article <1598@oregon.uoregon.edu> michelbi@oregon.uoregon.edu (Michel Biedermann) writes: >How good (i.e. random) is the rand() function in MSC 5.1/QC 2.0? Here's one easy test: int i; double sum=0; for (i = 0; i < 20; i++){ while( (double)rand()/MAX_RAND > 0.0001); /* wait */ sum += (double)rand()/MAX_RAND; /* then do something random */ } printf( "%f\n", sum/20.0); On the VAX I use (BSD 4.3?) I get 0.44, on Mac MPW I get 0.43. (both are reasonable.) On at least one version of Turbo Pascal for the PC you will get 0.25 or less. (my boss had this persistant bug in a small simulation of random packet arrivals - the average packet size was max/4 or max/8, rather than max/2. Turns out his code looked like the code above.) Peter Desnoyers
pats@cup.portal.com (Pat T Shea) (05/09/89)
'asked the same question and hung the following Quick 'n Dirty together . . . . . MSC v5.1 /* ----------SnipSnipSnipSnipSnipSnip--------- */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys\types.h> #include <sys\timeb.h> #define MAX_RAND 100 extern void main( int argc, char * *argv ); extern int random( int r) ; extern void randinit( void ); extern void moment( double data[], register int n, double *ave, double *adev, double *sdev, double *svar, double *skew, double *curt ); void main( int argc, char **argv ) { register int i, j; const int k = atoi( argv[1] ); unsigned long r[MAX_RAND]; double hits[MAX_RAND + 1], average = 0.0, *p_average, ave_dev = 0.0, *p_ave_dev, std_dev = 0.0, *p_std_dev, std_var = 0.0, *p_std_var, skew = 0.0, *p_skew, kurtosis = 0.0, *p_kurtosis; time_t start, end; if ( argc < 2 || k < 2 || k > MAX_RAND ) { printf( "\a\n\tSYNTAX: t_rand <n>\n\n\t" ); printf( "Any number, greater than 1 but less " ); printf( "than or equal to %d !!.....\n\n", MAX_RAND ); exit( 1 ); } /* Initialize the Random Number generator based on SysTime */ randinit(); /* Get start time */ time( &start ); /* Set pointers and zero out accumulator buckets.... */ p_average = &average; p_ave_dev = &ave_dev; p_std_dev = &std_dev; p_std_var = &std_var; p_skew = &skew; p_kurtosis = &kurtosis; for ( j = 0; j < MAX_RAND; j++ ) { r[j] = 0; } for ( j = 0; j < MAX_RAND + 1; j++ ) { hits[j] = 0.0; } /* and loop like a mad.... */ printf( "\n\t\tRunning 500,000 iterations....\n\n" ); printf( "\n\tThis takes 'bout 5 minutes on an IBM XT @ 4.77MHz\n" ); printf( "\t\tand 17-18 seconds on a COMPAQ 386/20 !!\n\n" ); for ( j = 0; j < 20; j++ ) { for ( i = 0; i < 25000; i++ ) { r[random( k )]++; } } printf( "\aFor %d Random Numbers in the range, 0 to %d .....\n\n\t", k, k - 1 ); for ( j = 0; j > MAX_RAND; j++ ) { if ( r[j] ) { printf( "%4d was hit...... %9lu times or %7.4f%%.\n\t", j, r[j], ( (double)( r[j] ) / 5000 )); } } /* Load up 'double' array and calculate statistics */ for ( j = 0; j < MAX_RAND; j++ ) { hits[j + 1] = (double) r[j]; } moment( hits, k, p_average, p_ave_dev, p_std_dev, p_std_var, p_skew, p_kurtosis ); printf( "\tMEAN of Hits was %13.5f\n", average ); printf( "\t\tAVE DEV of Hits was %10.2f\n", ave_dev ); printf( "\t\tSTD DEV of Hits was %10.2f\n", std_dev ); printf( "\t\tVARIANCE of Hits was %9.2f\n", std_var ); printf( "\tSKEWNESS was %f, ", skew ); printf( "and KURTOSIS was %f.\n", kurtosis ); printf( "\tThe STD DEV as a Percent of the MEAN is %7.5f%%.\n\n", 100 * std_dev / average ); time( &end ); printf( "\t\tThe Elapsed Time was %.0f seconds.\n\n", difftime( end, start )); exit( 0 ); } /*********************************************************************** * * to generate random integers * in the range of 0 to ( numb - 1 )....... * /Pat Shea @ Psi! 11-19-87 * *****/ int random( register int numb ) { long int raw_rand; raw_rand = (long) rand(); return( (int)( raw_rand * numb / 32768 )); } /*********************************************************************** * * void randinit( void ) * * Initializes the Random Number generator with an unsigned integer * in the range 0 to 65535. This 'seed' number is derived by * checking the System Clock, determining the number of SECONDS * since January 01, 1970, dividing this seconds number by 65535, * and 'seeding' with the remainder from the division. OR..... * there are 65,000+ possible 'seeds' or initializers for the * random sequences thus generated. Other techniques involve * seeding off the thousandths of a second on the System Clock * but this is NOT bullet proof in that not all systems maintain * that parameter, AND there are only 1000 possible seeds. If * that paramenter is not present, the random number generator * will always present the same sequence, seeded of the base * of '1'. This risk in using that parameter is TOO HIGH. * * /Pat Shea @ Psi! 11-19-87 *****/ void randinit( void ) { struct timeb sys_time; ftime( &sys_time ); srand( (unsigned int) ( sys_time.time % 65535L )); return; } /*********************************************************************** * * NAME: * moment.c - crunches elementary statistics * * adapted * from - Numeric Recipes in C - The Art of Scientific Computing * by Press, Flannery, Teukolsky and Vetterling * Cambridge University Press 1988 p475f. * * - bulletpruf'd and ANSI'd /PatS 06-15-88 * * SYNOPSIS: * void moment( double data[], register int n, double *ave, * double *adev, double *sdev, double *svar, * double *skew, double *curt ) * ****/ #include <conio.h> #include <math.h> void moment( double data[], register int n, double *ave, double *adev, double *sdev, double *svar, double *skew, double *curt ) { register int j; double p, s = 0.0; *adev = ( *svar ) = ( *skew ) = ( *curt ) = 0.0; if ( n <= 1 ) { (void) cputs( "\n\n\rMUST have at least 2 " ); (void) cputs( "observations for \"MOMENT\" to work !!\n\n\r" ); } for ( j = 1; j <= n; j++ ) { s += data[j]; } *ave = ( s / n ); for ( j = 1; j <= n; j++ ) { *adev += fabs( s = data[j] - ( *ave )); *svar += ( p = s * s ); *skew += ( p *= s ); *curt += ( p *= s ); } *adev /= n; *svar /= ( n - 1 ); *sdev = sqrt( *svar ); if ( *svar ) { *skew /= ( n * ( *svar ) * ( *sdev )); *curt = ( *curt ) / ( n * ( *svar ) * ( *svar )) - 3.0; } else { (void) cputs( "\n\n\rCannot calculate skew/kurtosis when " ); (void) cputs( "variance is 0.0 !! ( in \"MOMENT\" )\n\n\r" ); } return; }
dpgerdes@osiris.cso.uiuc.edu (05/09/89)
/* Written 11:26 am May 7, 1989 by michelbi@oregon.uoregon.edu in osiris.cso.uiuc.edu:comp.lang.c */ /* ---------- "Randomness of MSC 5.1 rand()" ---------- */ How good (i.e. random) is the rand() function in MSC 5.1/QC 2.0? Press, Flannery, Teukolski, and Vetterling of "Numerical Recipies in C" fame caution the reader to be "very, very suspicious" of any system-supplied rand() function. Does anybody have any comments on Microsoft's rand() function? Thank you for the help. Michel Biedermann U. of Oregon ZENITH Student Rep. /* End of text from osiris.cso.uiuc.edu:comp.lang.c */