my %bias = (1 => 1, 2 => 1); #### $rand = $k if rand($sum += $v) <= $v; # This simplifies to: # $rand = 1 if rand(1) <= 1 # this is always true. That's wrong. #### my $sum = 0; $sum += $_ foreach (values %bias); my $target = rand($sum); $sum = 0; while (my ($k, $v) = each %bias) { if ($target <= ($sum += $v)) { $rand = $k; last; } }