http://www.perlmonks.org?node_id=1001714


in reply to rand() precision low, looking for a fast way to get high precision rand float?

I want if() to be true at a rate of 1/40.000, however, rand() is not precise enough and outputs 0 quite often

That's not the way random works. It doesn't guarantee 1/40000, if it did, it would not be "random".

It only guarantees that the ratio will tend towards 1/40000 over time.

Most times it will produce 1/40000; but sometimes it will be 0/40000; sometimes 2/40000; occasionally 3/40000; very occasionally even 4/40000; but over time they will tend to balance each other out and the ratio will tend to get closer and closer to 1/40000.

Try running this for a while to see how it works:

#! perl -slw use strict; use Math::Random::MT qw[ rand ]; use constant LIMIT => 1 / 40000; $|++; my( $aveTrue, $aveFalse ) = (0,0); while( 1 ) { my( $true, $false ) = (0,0); for( 1 .. 40000 ) { if( rand() < LIMIT ) { ++$true; } else { ++$false; } } $aveTrue += $true; $aveFalse += $false; printf "\rThis time: $true/$false; Accumulate ratio: %f / 40000", +$aveTrue / ( $aveFalse / 40000 ); } __END__ C:\test>1001701.pl This time: 0/40000; Accumulate ratio: 0.995570 / 40000

If you need to always get one true from every 40,000, then use:

use List::Util qw[ shuffle ]; my @numbs = shuffle 1 .. 40000; for my $num ( @numbs ) { if( $num == 1 ) { ... } }

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

RIP Neil Armstrong