[comp.lang.perl] random numbers?

jas@ISI.EDU (Jeff Sullivan) (02/09/91)

Is there some problem with perl's srand and rand functions?

I wrote this program which is supposed to generate a random number
between 1 and 20, ecept if it produces a 10 on the first (and
subsequent) try, in which case it adds the first  (and subsequent) 10s
to another random number between 1 and 20.  

This is the code:

#!/usr/bin/perl
srand;

$total = $roll = int(1+rand(20));

while ($roll == 10) {
        $roll = int(1+rand(20));
        $total += $roll;
}

print $total,"\n";


I wrote a test program to run this a lot of times in a row to test it.
Here's the program:

#!/usr/bin/perl
foreach (0..$ARGV[0]) {
        print `roll`;
}

Here's the output:

17
7
7
7
18
18
8
18
19
19
9
9
19
19
19
*24
*24
*24
20
20
20
20
20
20
*25
*25
*25
*25
*25
*25
20
20
20
20
11
11
11
11
11
1
1
1
1
1
11
11



Hardly looks random to me.

What am I doing wrong?

jas
--
--------------------------------------------------------------------------
Jeffrey A. Sullivan		| Senior Systems Programmer
jas@venera.isi.edu		| Information Sciences Institute
jas@isi.edu                    	| University of Southern California

flee@cs.psu.edu (Felix Lee) (02/11/91)

>Is there some problem with perl's srand and rand functions?

srand() with no arguments does srand(time), and the current time of
day is not a very good seed.

One problem is it doesn't change quickly enough.  The following:
	#!/bin/csh -f
	repeat 10 perl -e 'srand; printf "%.3f ", rand(10);'
will tend to print things like:
	3.158 3.158 8.296 8.296 8.296 8.296 8.296 8.296 3.435 3.435
All the "8.296"s were produced in the same second.

Another problem is the current time of day is monotonically
increasing.  rand() is a simple linear congruential random number
generator (LCRG), typically something like this:
	seed = (seed * 1103515245 + 1234) & 0x7fffffff;
	return seed;
Perl takes this result and divides it by 2**31, turning it into a
floating point number between 0 and 1.

A simple linear function applied to simple, monotonically
increasing values will produce simple results.  The following:
	#!/usr/bin/perl
	for $s (1..10) {
		srand $s;
		for (1..8) {
			printf "%.3f ", rand(10);
		}
		print "\n";
	}
will print something like:
	5.139 1.757 3.087 5.345 9.476 1.717 7.022 2.264
	0.277 6.963 3.125 3.941 7.885 8.269 9.148 8.504
	5.416 2.169 3.163 2.537 6.293 4.821 1.274 4.743
	0.555 7.375 3.202 1.133 4.702 1.372 3.399 0.983
	5.693 2.581 3.240 9.728 3.111 7.924 5.525 7.223
	0.832 7.787 3.278 8.324 1.519 4.475 7.651 3.462
	5.971 2.993 3.317 6.920 9.928 1.027 9.776 9.702
	1.109 8.199 3.355 5.515 8.336 7.579 1.902 5.941
	6.248 3.404 3.393 4.111 6.745 4.130 4.027 2.181
	1.386 8.610 3.432 2.707 5.154 0.682 6.153 8.421
Note how predictable each column is, especially column 3.

Doing something like:
	srand(time + 251 * $$);
	rand; rand; rand; srand(rand(32767));
makes the problem less apparent.  But LCRGs suffer from many flaws.
Avoid rand() if you want good random numbers.
--
Felix Lee	flee@cs.psu.edu

tkacik@kyzyl.mi.org (Tom Tkacik) (02/11/91)

In article <3#3Gz8.j@cs.psu.edu>, flee@cs.psu.edu (Felix Lee) writes:
> >Is there some problem with perl's srand and rand functions?

> makes the problem less apparent.  But LCRGs suffer from many flaws.
> Avoid rand() if you want good random numbers.

Would it be difficult to put into the Config script, a check to see if
either random(BSD) or lrand48(SYSV) exist, and to allow Perl to use them?
Both of these are supposed to be much better random number
generators than rand().

-- 
Tom Tkacik                |
tkacik@kyzyl.mi.org       |     To rent this space, call 1-800-555-QUIP.
...!rphroy!kyzyl!tkacik   |

wengland@stephsf.stephsf.com (Bill England) (02/12/91)

In article <3#3Gz8.j@cs.psu.edu> flee@cs.psu.edu (Felix Lee) writes:
>>Is there some problem with perl's srand and rand functions?
 
 No Jeff, the problem is using srand over and over with a very
 similar initial key.  ( You've probably figured that out by 
 now. )  Anyway, a further problem is that perl does NOT HAVE
 a built in random number generator.  Perl uses the random 
 number generator that was provided with your c compiler.  This
 may not be the best generator (see below).

 Quite quite a few religious zealots have been spurred to jihad by our 
 great prophet Knuth.  Who hath given unto his followers the holy mission 
 to free the world from "bad" random number generators. To quote from the
 scriptures;

Knuth vol 2, Seminumerical Algorithms, Page 176, problem 6;

    Look at the subroutine library of each computer installation in your 
    organization, and replace the random number generators by good ones.  
    Try to avoid being too shocked by what you find.

Other interesting articles on random number generators can be found
in the ACM in 1987, 88;

1> Stephen K. Park and Keith W. Miller, _Random Number Generators: Good 
ones are hard to find_, Commun. ACM 31,10 Oct 1988.

2> Pierre L'Ecuyer, _Efficient and Portable Combined Random Number 
Generators_, Commun. ACM 31,6 June 1988.

3> Shu Tezuka, _Walsh-Spectral Test for GFSR Pseudorandom Numbers_,
Comm. ACM 30,8 August 1987.

>
>[...]
>makes the problem less apparent.  But LCRGs suffer from many flaws.
>Avoid rand() if you want good random numbers.
>--
>Felix Lee	flee@cs.psu.edu

Ahhh, Contraire Monseiuer Felix,

 Using the methods described in <1> above it is quite possible
 to build a very _good_ random number function that uses an 
 Linear Congruential Generator ("LCG").  (Good is of course
 defined religiously and I refer such questions to Knuth Vol 2 
 chapter 3 and the rest of the references above.)

 In fact <1> describes a random number generator with a period
 of 2147483647 that can be implemented in a high level language
 (with integers) on  both 32 bit word and 16 bit word machines.
 The output of the generator under both architecture is 31 bits.

 Yes ... the exact same generator with the exact same sequence !

----

 Included Below is an implementation of the LCG algorithm of <1> 
 and patches to apply it to Perl 3.0@44 .

 Also, included is a Perl program that will generate a library,
 random.pl, that implements this generator, in Perl, on 'all' 
 systems. (Ok, maybe not *all* systems,  I'd like to know where it 
 doesn't work though ... )

---
#! /bin/sh

# Make a new directory for the random sources, cd to it, and run kits 1
# thru 1 through sh.  When all 1 kits have been run, read README.

echo "This is random 1.0 kit 1 (of 1).  If kit 1 is complete, the line"
echo '"'"End of kit 1 (of 1)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
mkdir  2>/dev/null
echo Extracting README.rand
sed >README.rand <<'!STUFFY!FUNK!' -e 's/X//'
X____References _______
X
X0> Knuth Vol 2, Seminumerical Algorithms.
X
X1> Stephen K. Park and Keith W. Miller, _Random Number Generators: 
X   Good ones are hard to find_, Commun. ACM 31,10 Oct 1988.
X
X2> Pierre L'Ecuyer, _Efficient and Portable Combined Random Number 
X   Generators_, Commun. ACM 31,6 June 1988.
X
X3> Shu Tezuka, _Walsh-Spectral Test for GFSR Pseudorandom Numbers_,
X   Comm. ACM 30,8 August 1987.
X
XThe random number generator used here is described in <1> above and
Xuses a standard Linear Congruential Generator ("LCG") equation that
XKnuth <0> talks about at great length.
X
X X(n+1) = (aX(n) + c) % m;
X
X a,c, and m are chosen to be:
X a = 7^5 = 16807
X m = 2^31 -1 = 2147483647
X c = 0
X
XAs the enclosed test programs indicate this generator can 
Xbe implemented in the Perl language.
X
X__ gen_rand_pl ___
X
XThis program 'gen_rand_pl' creates  the library random.pl using one 
Xof two algorithms.  Both of  these algorithms implement the same LCG but,
Xone of these libraries requires much less floating point accuracy than 
Xthe other.
X
XThe two different methods are tested and a random.pl is created that
Xwill work on your machine.
X
XThe float version of the library is fastest.  There is a chance that 
Xthis program will core out if your system has less than adequate 
Xfloating point numbers.  If the first test fails comment it out and try  
Xthe 'int' library only.
X
X** I believe that the second library or int version  should work 
X** everywhere.  Please Let me know if it doesn't.
X 
X---
X
X  The real fix of course is to link your own custom c or asm random 
X  number functions directly into Perl and dispense with the random 
X  number libraries above and the flawed rand() functions common to 
X  Unix.  
X
X  (See <1> for reasons that the standard Unix random number 
X   generator is flawed.)
X
X  "random.c" is a random number generator written in c that 
X  implements the algorithms discussed in <1> with integers (Not 
X  floating point). It, of course, blazes relative to the similar 
X  functions written in Perl.  This module may be linked directly into 
X  your version of Perl to replace your systems standard rand functions. 
X
X  Before you bother to apply the patch you can test this random number
X  generator to see if it will work on your system.
X
X
X__ Pre patch test you can run. __
X
X  $cc -DTEST1 random.c 
X  Will create an a.out that when run indicates if the LCG sequence is 
X  being generated correctly. 
X
X
X__ The Patch __
X
X  The enclosed patches will add checks to Perl's Configure and
X  Makefile.SH files that allow you to optionally compile and link
X  the new random.c program into Perl.
X
X1>  Check and make sure that your Perl source is version
X    3.0 at patchlevel 44. ( Repeat until true )
X
X2> Copy the files random.c, config.patch, and make.patch
X   to the directory where your Perl source is located.
X
X3> Apply the patches, one at a time and give the correct file
X   name to patch when prompted.
X
X   patch < config.patch
X   Name: Configure
X
X   patch < make.patch
X   Name: Makefile.SH
X
X
X4>  Run Configure and create a Perl release as you normally would.
X
X    An additional line will appear during the Configure that asks 
X    you if you want to use the random number generator that comes 
X    with Perl.  The random.o file is tested as well to make certain
X    that it works.
X
X
X5>  After Perl is compiled and all of the standard tests are successful,
X    run the test program 'rand_test'. (i.e. ./perl rand_test )
X
X    This program will indicate if you actually linked the correct 
X    rand function into Perl and that it actually works.  
X
X
Xoo> There may be installations where very good random number generators
X    already exist.  For instance, I imagine that all Cray's have good 
X    generators shipped with them.
X
X    Oh yes ... Congratulations, you now have a very good and well 
X    tested random number function embedded in your Perl.
X
X
X--  BUGS ---
X
X (1)
X Perls eval.c divides by the wrong modulus 2147483648 instead of the
X actual modulus of 2147483647.  This should not cause a generator
X problem (i.e. you will still get the full cycle.) but, it is not
X technically correct. Also the Perl rand function _may_ have more 
X accuracy if the order of multiplication and division were reversed 
X in eval.c, again this will not affect quaility of the actual generator 
X and is highly machine and compiler dependent.
X
X (2)
X I did not modify the headers of Configure or Makefile.SH to indicate
X that these random number modifications were made.
!STUFFY!FUNK!
echo Extracting gen_rand_pl
sed >gen_rand_pl <<'!STUFFY!FUNK!' -e 's/X//'
X#!perl
Xeval "exec perl -S $0 $*"
X	if $running_under_some_shell;
X#
X#
X
X$_ = 'random.pl';
Xdie "Will not overwrite existing random.pl\n" if -e;
Xopen( RANDOM_LIB, '>'.$_ );
X
X  print "\nTesting fast version of LCG ...\n";
X  &Generate_float_pl;
X  exit 0 if &test_LCG;
X
X  print "\nTesting slower but more universal version of LCG ...\n";
X  &Generate_int_pl;
X  exit 0 if &test_LCG;
X
X  unlink 'random.pl';
X
X  print "random.pl has not been created.\n";
X  exit 1;
X
X#--- End of main -----
X
X##
X # LCG test function
X##
Xsub test_LCG{
X
X    # Point the local libraries to the same directory as this script.
X    split(/\//,$0);
X
X    @_[$#_]= 'random.pl';
X    $_ = join( '/', @_ );
X    do $_; 
X
X    &srand(1);
X
X    for( $seq=1; $seq<= 10000; $seq++){
X	&rand(32);
X
X	if( $seq == 10000){
X            if( &current_seed == 1043618065 ){
X		print"LCG random.pl library is successfully implemented.\n";
X		return 1;
X	    }else{
X		print"Random number library DOES NOT WORK! \n";
X		return 0;
X	   }  
X	}
X    }
X};
X
Xsub Generate_float_pl{
X$library=
Xq| package random_lib;
X##
X # Public Domain Work 1992, Stephen Software Systems, Inc.
X # This library is based on the following article;
X #
X # Stephen K. Park and Keith W. Miller, _Random Number Generators: Good
X # ones are hard to find_, Commun. ACM 31,10 Oct 1988.
X #
X # This library implements the Floating point version of this
X # algorithm and only works on systems that have at least
X # a 46 bit floating point mantissa.
X #
X # Functions implemented are srand and rand which work like
X # perl's standard srand and rand.  These are subroutines and
X # not internal perl functions.  The () is required when calling
X # them.
X # 
X # An additional routine is provided to give you the current 
X # random number seed.  This can be used for function verification.
X##
X$a= 16807;
X$m= 2147483647;
X
X1;
X##
X #
X##
Xsub main'srand{
X   $seed = pop(@_);
X
X   $seed = $^T unless defined $seed ;
X}
X##
X #
X##
Xsub main'rand{
X    local($value)=pop(@_);
X
X    $temp = $a * $seed;
X    $seed = $temp - $m * int( $temp / $m);
X    $seed / $m * $value;
X}
X##
X #
X##
Xsub main'current_seed{
X    $seed;
X}
X|;
Xprint RANDOM_LIB $library;
X}
X##
X #
X##
Xsub Generate_int_pl{
X$library=
Xq| package random_lib;
X##
X # Public Domain Work 1992, Stephen Software Systems, Inc.
X # This library is based on the following article;
X #
X # Stephen K. Park and Keith W. Miller, _Random Number Generators: Good
X # ones are hard to find_, Commun. ACM 31,10 Oct 1988.
X #
X # This library implements the 'integer' version of the LCG described
X # above and should work on all machines.
X #
X # Functions implemented are srand and rand which work like
X # perl's standard srand and rand.  These are subroutines and
X # not internal perl functions.  The () is required when calling
X # them.
X # 
X # An additional routine is provided to give you the current 
X # random number seed.  This can be used for function verification.
X##
X$a = 16807;
X$m = 2147483647;
X$q = 127773; # m / a
X$r = 2836;   # m % a
X
X1;
X##
X #
X##
Xsub main'srand{
X   $seed = pop(@_);
X
X   $seed = $^T unless defined $seed ;
X}
X##
X #
X##
Xsub main'rand{
X    local($value)=pop(@_);
X    local($lo,$hi,$test);
X
X    $hi = int($seed / $q);
X    $lo = int($seed % $q);
X
X    $test = $a * $lo - $r * $hi;
X    if ($test > 0 ) {
X	$seed = $test;
X    }else{
X	$seed = $test + $m;
X    }
X
X    $seed / $m * $value;
X}
X##
X #
X##
Xsub main'current_seed{
X    $seed;
X}
X|;
Xprint RANDOM_LIB $library;
X}
X
!STUFFY!FUNK!
echo Extracting random.c
sed >random.c <<'!STUFFY!FUNK!' -e 's/X//'
X/*
X *
X * This program is public domain and was written by William S. England
X * (Oct 1988).  It is based on an article by:
X *
X * Stephen K. Park and Keith W. Miller. RANDOM NUMBER GENERATORS:
X * GOOD ONES ARE HARD TO FIND. Communications of the ACM,
X * New York, NY.,October 1988 p.1192
X
XModifications;
X
X   Sun Feb 10 18:20:38 PST 1991
X    WSE, modified for replacement of random number object file
X    under unix and for use with Perl.
X
X The following is a portable c program for generating random numbers.
X The modulus and multipilier have been extensively tested and should
X not be changed except by someone who is a professional Lehmer generator
X writer.  THIS GENERATOR REPRESENTS THE MINIMUM STANDARD AGAINST WHICH
X OTHER GENERATORS SHOULD BE JUDGED. ("Quote from the referanced article's
X authors. WSE" )
X*/
X
X#include <stdio.h> 
X
X#define	m  (unsigned long)2147483647
X#define	q  (unsigned long)127773
X
X#define	a (unsigned int)16807
X#define	r (unsigned int)2836
X
X/*
X** F(z)	= (az)%m
X**	= az-m(az/m)
X**
X** F(z)  = G(z)+mT(z)
X** G(z)  = a(z%q)- r(z/q)
X** T(z)  = (z/q) - (az/m)
X**
X** F(z)  = a(z%q)- rz/q+ m((z/q) - a(z/m))
X** 	 = a(z%q)- rz/q+ m(z/q) - az
X*/
X
X/*
X**
X*/
Xunsigned long seed;
X
Xvoid srand( /* unsigned long*/ initial_seed)
Xunsigned long initial_seed;
X{
X    seed = initial_seed; 
X}
X/*
X**
X*/
Xunsigned long rand(/*void*/){
X
Xregister
Xint 	lo, hi, test;
X
X    hi   = seed/q;
X    lo   = seed%q;
X
X    test = a*lo - r*hi;
X
X    if (test > 0)
X	seed = test;
X    else
X	seed = test+ m;
X
X    return seed;
X}
X
X#ifdef TEST1
X/*  
X**   The result of running this program should be
X**   1043618065.  If this program does not yeild this
X**   value then your compiler has not implemented this
X**   program correctly.
X*/
X
Xmain(/*void*/)
X{
Xunsigned 
Xlong	n_rand;
X
Xregister int 	i;
Xint	success = 0;
X
X    srand(1);
X
X    for( i = 1; i <= 10001; i++){
X        n_rand = rand();
X
X        if( i> 9998)  
X	    printf("Sequence %5i, Seed= %10i\n", i, seed ); 
X
X	if( i == 10000) 
X	    if( seed == 1043618065 ) 
X		success = 1;
X    }
X
X    if (success){
X	printf("The random number generator works correctly.\n\n");
X	exit(0);
X    }else{
X	printf("The random number generator DOES NOT WORK!\n\n");
X	exit(1);
X    }
X}
X#endif
!STUFFY!FUNK!
echo Extracting config.patch
sed >config.patch <<'!STUFFY!FUNK!' -e 's/X//'
X199a200,202
X> randomsrc=''
X> randomobj=''
X> usemyrandom=''
X1169c1172
X< : check for size of random number generator
X---
X> : check for alignment bountries
X2490c2493
X< : check for size of random number generator
X---
X> : determine if we can use Park and Millers random function
X2492c2495
X< case "$randbits" in
X---
X> case "$usemyrandom" in
X2494,2495c2497,2528
X<     echo "Checking to see how many bits your rand function produces..."
X<     $cat >try.c <<'EOCP'
X---
X>     echo "Checking to see if Perl's new rand() function will work ..."
X>     if $cc $ccflags -DTEST1 ../random.c -o try >/dev/null 2>&1 ; then
X> 	if ./try 2>&1; then 
X> 	    dflt='y'
X> 	else
X> 	    dflt='n'
X> 	    echo "(Perls random number generator does not seem to work ...)"
X> 	fi
X>     else
X> 	dflt='n'
X> 	echo "(I can't seem to compile the test program...)"
X>     fi
X>     ;;
X> *)  dflt="$usemyrandom"
X>     ;;
X> esac
X> rp="Do you wish to to use the rand function that comes with $package? [$dflt]"
X> $echo $n "$rp $c"
X> . myread
X> case "$ans" in
X> '') ans=$dflt;;
X> esac
X> usemyrandom="$ans"
X> case "$ans" in
X> y*) randomsrc='random.c'; randomobj='random.o';;
X> *) randomsrc=''; randomobj='';;
X> esac
X> 
X> 
X> : check for size of random number generator
X> echo " "
X>         $cat >try.c <<'EOCP'
X2512,2517c2545,2554
X<     if $cc $ccflags try.c -o try >/dev/null 2>&1 ; then
X< 	dflt=`./try`
X<     else
X< 	dflt='?'
X< 	echo "(I can't seem to compile the test program...)"
X<     fi
X---
X> case "$randbits" in
X> '')
X>     echo "Checking to see how many bits the rand function produces..."
X>     case "$usemyrandom" in
X>     y*) if $cc $ccflags try.c  ../random.c -o try >/dev/null 2>&1 ; then
X>   	    dflt=`./try`
X>         else
X>  	    dflt='?'
X> 	    echo "(I can't seem to compile the test program...)"
X>         fi
X2519,2520c2556,2561
X< *)
X<     dflt="$randbits"
X---
X>     *)  if $cc $ccflags try.c -o try >/dev/null 2>&1 ; then
X> 	    dflt=`./try`
X>         else
X>     	    dflt='?'
X> 	    echo "(I can't seem to compile the test program...)"
X>         fi
X2521a2563,2566
X>     esac
X>     ;;
X> *) dflt="$randbits"
X>     ;;
X2864a2910,2912
X> randomsrc='$randomsrc'
X> randomobj='$randomobj'
X> usemyrandom='$usemyrandom'
!STUFFY!FUNK!
echo Extracting rand_test
sed >rand_test <<'!STUFFY!FUNK!' -e 's/X//'
X#!perl
Xeval "exec perl -S $0 $*"
X	if $running_under_some_shell;
X
Xsrand(1);
X
Xforeach $seq(1..10000){
X
X    $seed = rand(2147483648);
X
X    if( $seq == 10000){
X        print $seed, "\n";
X        if( $seed == 1043618065 ){
X            print"random.c is successfully integrated into Perl.\n";
X        }else{
X            print"random.c DID NOT install into Perl correctly! \n";
X        }  
X    }
X}
!STUFFY!FUNK!
echo Extracting make.patch
sed >make.patch <<'!STUFFY!FUNK!' -e 's/X//'
X88a89,90
X> randomsrc = $randomsrc
X> randomobj = $randomobj
X117c119
X< c3 = stab.c str.c toke.c util.c usersub.c
X---
X> c3 = stab.c str.c toke.c util.c usersub.c $(randomsrc)
X123c125
X< obj3 = stab.o str.o toke.o util.o
X---
X> obj3 = stab.o str.o toke.o util.o $(randomobj)
X129c131
X< tobj3 = tstab.o tstr.o ttoke.o tutil.o
X---
X> tobj3 = tstab.o tstr.o ttoke.o tutil.o $(randomobj)
!STUFFY!FUNK!
echo " "
echo "End of kit 1 (of 1)"
cat /dev/null >kit1isdone
run=''
config=''
for iskit in 1; do
    if test -f kit${iskit}isdone; then
	run="$run $iskit"
    else
	todo="$todo $iskit"
    fi
done
case $todo in
    '')
	echo "You have run all your kits.  Please read README."
	for combo in *:AA; do
	    if test -f "$combo"; then
		realfile=`basename $combo :AA`
		cat $realfile:[A-Z][A-Z] >$realfile
		rm -rf $realfile:[A-Z][A-Z]
	    fi
	done
	rm -rf kit*isdone
	;;
    *)  echo "You have run$run."
	echo "You still need to run$todo."
	;;
esac
: Someone might mail this, so...
exit
-- 
 +-  Bill England,  wengland@stephsf.COM -----------------------------------+
 |   * *      H -> He +24Mev                                                |
 |  * * * ... Oooo, we're having so much fun making itty bitty suns *       |
 |__ * * ___________________________________________________________________| 

andy@cs.caltech.edu (Andy Fyfe) (02/13/91)

In article <292@kyzyl.mi.org> tkacik@kyzyl.mi.org (Tom Tkacik) writes:
>Would it be difficult to put into the Config script, a check to see if
>either random(BSD) or lrand48(SYSV) exist, and to allow Perl to use them?

Random is part of the freed BSD sources.  Perl could be distributed with
it, potentially.

Andy Fyfe					andy@cs.caltech.edu

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/14/91)

In article <292@kyzyl.mi.org> tkacik@kyzyl.mi.org (Tom Tkacik) writes:
: In article <3#3Gz8.j@cs.psu.edu>, flee@cs.psu.edu (Felix Lee) writes:
: > >Is there some problem with perl's srand and rand functions?
: 
: > makes the problem less apparent.  But LCRGs suffer from many flaws.
: > Avoid rand() if you want good random numbers.
: 
: Would it be difficult to put into the Config script, a check to see if
: either random(BSD) or lrand48(SYSV) exist, and to allow Perl to use them?
: Both of these are supposed to be much better random number
: generators than rand().

Well, you can probably get away with -Drand=random -Dsrand=srandom.
(Similarly for lrand48 and srand48, I suspect.)  It'll run a bit slower.
And some of the JAPH scripts won't work.  Not that those JAPHs were
portable in the first place...

Larry

merlyn@iwarp.intel.com (Randal L. Schwartz) (02/14/91)

In article <11422@jpl-devvax.JPL.NASA.GOV>, lwall@jpl-devvax (Larry Wall) writes:
| And some of the JAPH scripts won't work.  Not that those JAPHs were
| portable in the first place...

One, Larry.  One.  I wrote only *one* that used srand/rand.  Before
you quickly thwacked me for being non-portable.

OK, so "one" is a subset of "some". :-)

And, who says a JAPH has to be portable?

$_ = `hostname`; s/..(.)(.).(.)(.)/Ju\3t \1noth\4\2 P\4\2l h\1ck\4\2,/; print
# works on "iwarpse"..... :-)
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

gamin@ireq-robot.hydro.qc.ca (Martin Boyer) (02/14/91)

In article <11422@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:
>In article <292@kyzyl.mi.org> tkacik@kyzyl.mi.org (Tom Tkacik) writes:
>: [...]
>: Would it be difficult to put into the Config script, a check to see if
>: either random(BSD) or lrand48(SYSV) exist, and to allow Perl to use them?
>
>Well, you can probably get away with -Drand=random -Dsrand=srandom.

That's what I've been doing for the last ~6 months.  No problem so
far.  I even suggested it to Larry a while ago, by private email, but
this may not be a high priority.

-- 
Martin Boyer                            mboyer@ireq-robot.hydro.qc.ca
Institut de recherche d'Hydro-Quebec    mboyer@ireq-robot.uucp
Varennes, QC, Canada   J3X 1S1
+1 514 652-8412

darrylo@hpnmdla.HP.COM (Darryl Okahata) (02/14/91)

In comp.lang.perl, tkacik@kyzyl.mi.org (Tom Tkacik) writes:

> Would it be difficult to put into the Config script, a check to see if
> either random(BSD) or lrand48(SYSV) exist, and to allow Perl to use them?
> Both of these are supposed to be much better random number
> generators than rand().

     A better solution would be to grab the BSD random()/srandom()
routines from nethack, and use those.  That way, you don't have to worry
about random number generator differences between various machines.

     -- Darryl Okahata
	UUCP: {hplabs!, hpcea!, hpfcla!} hpnmd!darrylo
	Internet: darrylo%hpnmd@hp-sde.sde.hp.com

DISCLAIMER: this message is the author's personal opinion and does not
constitute the support, opinion or policy of Hewlett-Packard or of the
little green men that have been following him all day.

wengland@stephsf.stephsf.com (Bill England) (02/15/91)

  That rand_test script in the previous post was a bit slow.

  Here is a much faster one:
---
#!perl

srand(1);

$seq = 0;
while ( $seq++ < 10000){

    $seed = rand(2147483648);

    if( $seq == 10000){
        print $seed, "\n";
        if( $seed == 1043618065 ){
            print"random.c is successfully integrated into Perl.\n";
        }else{
            print"random.c DID NOT install into Perl correctly! \n";
        }  
    }
}
-- 
 +-  Bill England,  wengland@stephsf.COM -----------------------------------+
 |   * *      H -> He +24Mev                                                |
 |  * * * ... Oooo, we're having so much fun making itty bitty suns *       |
 |__ * * ___________________________________________________________________| 

asmodeus@tree.uucp (Jon Ballard) (02/16/91)

In article <16698@venera.isi.edu> jas@ISI.EDU (Jeff Sullivan) writes:
>Is there some problem with perl's srand and rand functions?
[...]
>#!/usr/bin/perl
>srand;
>
>$total = $roll = int(1+rand(20));
>
>while ($roll == 10) {
>        $roll = int(1+rand(20));
>        $total += $roll;
>}
>
>print $total,"\n";
[...]
>I wrote a test program to run this a lot of times in a row to test it.
>Here's the program:
>
>#!/usr/bin/perl
>foreach (0..$ARGV[0]) {
>        print `roll`;
>}
>
>Here's the output:
>
>17
>7
>7
>7
>18
>18
>8
>18
>19
>19
>9
>9
>19
>19
>19
>*24
>*24
>*24
[... etc]

Doesn't srand with no arguments take the current time as the seed value?
Look like its doesn't look random becuase the seed value is the same untill
another second click.  If so then that why it doesn't look so random.  
You could always d something weird like  "srand (time + $$)" to set the seed.
-- 
		    Jonathan Ballard (a.k.a Asmodeus)
	    UNIX Tree BBS - A new generation in BBS programs! 
EMAIL: csusac.ecs.csus.edu!tree!asmodeus    ...!pacbell!sactoh0!tree!asmodeus
		...!ucbvax!ucdavis!csusac!tree!asmodeus