sub weightedprob { my %bias = @_; my ($total, %boundaries); # prepare the boundary map foreach ( sort { $bias{$b} <=> $bias{$a} } keys %bias ) { $total += $bias{$_}; $boundaries{$total} = $_; } # get a random place on the boundary map, look it up my $random = rand($total); foreach ( sort { $a <=> $b } keys %boundaries ) { return $boundaries{$_} if $random < $_; } } my $result = weightedprob( 1 => 3.1, 2 => 2.0234, 3 => 1.7, 4 => 1.542232, 5 => 1.321249563, 6 => 1.0142, );