use Math::BigFloat; my %score_for; my $loops = 100; my $step = 500; my $inputs = 100_000; foreach my $i ( 1 .. $loops ) { my $n = $i * $step; my @input = map { rand $n } 1 .. $inputs; my $correct = perfect_average( @input ); my $bad = bad_average( @input ); my $better = better_average( @input ); my $bad_diff = $correct->copy()->bsub( $bad )->babs(); my $better_diff = $correct->copy()->bsub( $better )->babs(); my $cmp = $bad_diff->bcmp( $better_diff ); my $winner = ( $cmp > 0 ) ? 'bad' : ( $cmp < 0 ) ? 'better' : 'tie'; push @{$score_for{ $winner }}, $n; print "n: $n, winner: $winner\n"; } foreach my $method ( qw( bad better tie ) ) { my $score = scalar @{$score_for{ $method }}; my $avg = int perfect_average( @{$score_for{ $method }} ); print "'$method' won $score (avg $avg)\n"; } sub perfect_average { my $acc = Math::BigFloat->new(); $acc->badd( $_ ) for @_; $acc->bdiv( scalar @_ ); return $acc; } sub bad_average { my $acc = 0; $acc += $_ for @_; return $acc / @_; } sub better_average { my $acc = 0; $acc += $_/@_ for @_; return $acc; }