use strict ; use warnings ; my $RUNS = 100_000 ; my $data = [[a => 0.1], [b => 0.5], [c => 0.4], [c => 0]] ; my %count; foreach (1 .. $RUNS) { my $total_weight = $data->[-1]->[1] ; if (!$total_weight) { $total_weight += $_->[1] for @$data ; $data->[-1]->[1] = $total_weight ; } ; my $pick; my $r = rand($total_weight) ; foreach (@$data) { if (($r -= $_->[1]) < 0) { $pick = $_->[0] ; last ; } ; } ; $count{$pick}++ ; } ; while (my ($k, $v) = each %count) { printf "%s: %5.2f%%\n", $k, 100 * $v / $RUNS ; } ; __END__ c: 39.89% a: 9.92% b: 50.19%