#!/usr/bin/perl -w
use strict;
=pod
FROM PERLFAQ4
Computers are good at being predictable and bad at being random (despite
appearances caused by bugs in your programs :-).
http://www.perl.com/CPAN/doc/FMTEYEWTK/random , courtesy of Tom Phoenix,
talks more about this.
John von Neumann said,
"Anyone who attempts to generate random numbers by deterministic means
is, of course, living in a state of sin."
If you want numbers that are more random than rand with srand provides, you
should also check out the Math::TrulyRandom module from CPAN. It uses the
imperfections in your system's timer to generate random numbers, but takes
this quite a while. If you want a better pseudorandom generator than comes
with your operating system, look at "Numerical Recipes in C" at
http://www.nr.com/
EXPLANATION OF KEY VARIABLES USED BELOW
$size = desired size of the newly generated output array
@randed = the array we're going to generate, randomize, and return
$bignums = use this number as a divisor to split up huge numbers into
C longs that are small enough to be handled by your system
architecture and/or Perl binary (depending on how compiled)
You really shouldn't need to mess with this unless you start
fooling around with insanely titanic numbers. Setting this
too low will decrease the entropy acheived per pass and
requiring more passes to generate a randomized array. The
array will also be less randomized.
=cut
my($started) = time;
my($size) = $ARGV[0] || die(q[C'mon man! Gimme an array size!]);
my($bignums) = $ARGV[1] || 256; # put bignum def right here.
my($splits) = sprintf('%.0f',$size / $bignums);
my(@randed) = ();
if ($bignums && $size > $bignums) {
my($split) = 0;
for (my($i) = 1; $i <= $size; $i += $bignums) {
print
(
qq[looping over split @{[++$split]} of $splits...],
qq[\n] x 2
);
my($endchunk) = ($bignums + $i > $size) ? $size : ($bignums + $i) - 1;
splice
(
@randed,
eval { (scalar(@randed)) ? rand(scalar(@randed)) : 0 },
0,
&randomize($i .. $endchunk)
)
}
}
else {
push( @randed, &randomize(1 .. $size))
}
sub randomize {
my(@gen) = @_;
my($len) = scalar(@gen);
my($seq) = 1;
my($ii) = 0;
# make as many passes over @gen as it takes to get it 100% randomized
while ($seq > 0) {
# make one pass over @gen
for ( my($iii) = 0; $iii <= $len; $iii++ ) {
my($randelem) =
splice
(
@gen,
rand($len),
1,
);
@gen = ( $randelem, @gen );
}
# figure out how much entropy occurred in @gen during this pass
my($iseq) = 0; for ( my($iv) = 0; $iv < ($len - 1); $iv++ ) {
++$iseq if ( $gen[ $iv+1 ] - $gen[ $iv ] == 1)
}
$seq = $iseq;
# report
print(<<__pass__); ++$ii
After @{[ $ii+1 ]} passes, present \@randed chunk is \%@{[
100 - (($iseq / $len) * 100) ]} (size @{[ scalar(@gen) ]}) percent random-ed
__pass__
}
return(@gen);
}
print(<<__final__);
---------
randomized array contains @{[ scalar(@randed) ]} elements:
__final__
print(shift(@randed), qq[\n]) while (@randed);
print(<<__took__) and exit;
took @{[ (time - $started) / 10 ]} seconds
__took__
=pod
AUTHOR
-Tommy Butler, professional contractor and open source proponent
Atrixnet™, for Internet Business Software®
http://atrixnet.com
6711 Forest Park Dr
Arlington, TX
76001
COPYRIGHT
Copyright Tommy Butler. All rights reserved
BUGS
Please report any bugs to me
=cut