# Round $v to nearest integer
sub round { sprintf("%.0f", shift) }

# Add up the arguments
sub sum {
  my $s = 0;
  $s += $_ for @_;
  $s;
}

sub fudge_numbers {
  my ($prec, @d) = @_;
  my $scale = 10 **  $prec;
  my $sum = sum(@d);

  # Scale data so that all significant digits are *left* of the decimal point
  @p = map $_*100*$scale/$sum, @d; 
  @r = map round($_), @p;       # rounded versions of @p
  @e = map $r[$_]-$p[$_], (0 .. $#r); # error

  # This is the number of jots by which the answer is too high.
  my $total_error = round(sum(@e));

  if ($total_error != 0) {
    # -1: numbers need to be decreased. +1: numbers need to be increased
    my $fudge = $total_error > 0 ? -1 : 1;

    # We want total_error equal to zero.
    # To achieve this, we will add a jot to the low numbers, 
    # or subtract a jot from the high numbers, as needful.
    
    for (0..$#r) {
      next unless $e[$_] * $fudge < 0; # Error goes the wrong way on this value
      $r[$_] += $fudge;          # Adjust value
      $total_error += $fudge;          
      last if $total_error == 0;
    }
  }

  map $_ / $scale, @r;  # Scale data back to percentages
}

my @a = fudge_numbers(10, 1, 1, 1);
print "@a\n";
