[ 0 0 0 0 0 5.88235294117647 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 23.5294117647059 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 47.0588235294118 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 100 ] #### foo: 5.88235294117647% bar: 17.6470588235294% baz: 23.5294117647059% quux: 52.9411764705882% #### c:\test>junk -N=1e2 foo frequency 4.000% bar frequency 18.000% baz frequency 23.000% quux frequency 55.000% c:\test>junk -N=1e3 foo frequency 5.300% bar frequency 15.400% baz frequency 25.600% quux frequency 53.700% c:\test>junk -N=1e4 foo frequency 5.640% bar frequency 17.690% baz frequency 23.370% quux frequency 53.300% c:\test>junk -N=1e5 foo frequency 5.961% bar frequency 17.379% baz frequency 23.683% quux frequency 52.977% c:\test>junk -N=1e6 foo frequency 5.885% bar frequency 17.662% baz frequency 23.446% quux frequency 53.007% #### #! perl -slw use strict; use List::Util qw[ sum ]; our $N ||= 1_000; our $SCALE ||= 100; sub pickGen { my $total = sum @_; my $accum = 0; my @weights = map{ my $fencepost = $_[ $_ ] * $SCALE / $total; ( ( $_ ) x $fencepost, $accum += $fencepost ) } 0 .. $#_; return sub { my $randValue = rand $SCALE; my $index = $weights[ $randValue ]; return $index if $index == int $index; return $weights[ int( $randValue + ( $randValue <=> $index ) ) ] }; } my @array = ( ["foo", 1], ["bar", 3], ["baz", 4], ["quux", 9] ); my $picker = pickGen( map $_->[1], @array ); my %choices; $choices{ $array[ $picker->() ][ 0 ] }++ for 1 .. $N; printf "%10s frequency %.3f%%\n", $_, $choices{ $_ } *100 / $N for sort{ $choices{ $a } <=> $choices{ $b } } keys %choices;