Freeware JavaScript Editor Perl Tutorials

↑

Main Page |

## Recipe 2.9 Generating Biased Random Numbers## 2.9.1 ProblemYou want to pick a random value where the probabilities of the values are not equal (the distribution is not even). You might be trying to randomly select a banner to display on a web page, given a set of relative weights saying how often each banner is to be displayed. Alternatively, you might want to simulate behavior according to a normal distribution (the bell curve). ## 2.9.2 SolutionIf you want a random value distributed according to a specific function—e.g., the Gaussian (Normal) distribution—consult a statistics textbook to find the appropriate function or algorithm. This subroutine generates random numbers that are normally distributed, with a standard deviation of 1 and a mean of 0: sub gaussian_rand { my ($u1, $u2); # uniformly distributed random numbers my $w; # variance, then a weight my ($g1, $g2); # gaussian-distributed numbers do { $u1 = 2 * rand( ) - 1; $u2 = 2 * rand( ) - 1; $w = $u1*$u1 + $u2*$u2; } while ($w >= 1 || $w = = 0); $w = sqrt( (-2 * log($w)) / $w ); $g2 = $u1 * $w; $g1 = $u2 * $w; # return both if wanted, else just one return wantarray ? ($g1, $g2) : $g1; } If you have a list of weights and values you want to randomly pick
from, follow this two-step process: first, turn the weights into a
probability distribution with # weight_to_dist: takes a hash mapping key to weight and returns # a hash mapping key to probability sub weight_to_dist { my %weights = @_; my %dist = ( ); my $total = 0; my ($key, $weight); local $_; foreach (values %weights) { $total += $_; } while ( ($key, $weight) = each %weights ) { $dist{$key} = $weight/$total; } return %dist; } # weighted_rand: takes a hash mapping key to probability, and # returns the corresponding element sub weighted_rand { my %dist = @_; my ($key, $weight); while (1) { # to avoid floating point inaccuracies my $rand = rand; while ( ($key, $weight) = each %dist ) { return $key if ($rand -= $weight) < 0; } } } ## 2.9.3 DiscussionThe # gaussian_rand as shown earlier $mean = 25; $sdev = 2; $salary = gaussian_rand( ) * $sdev + $mean; printf("You have been hired at \$%.2f\n", $salary); The Math::Random module implements this and other distributions for you: use Math::Random qw(random_normal); $salary = random_normal(1, $mean, $sdev); The Also, the CPAN module Math::Random has functions to return random numbers from a variety of distributions. ## 2.9.4 See AlsoThe |

Main Page |

↓

JavaScript Verifier Perl Tutorials

©