I don't know how many people here remember the thread on "weird math" but here's the question that I posed awhile back...

I've got a script that takes numbers similar to those below and then rounds
them and adds them together using code similar to what is below.


    #!/usr/bin/perl -w

    use strict;
    my $item_1 = "1.655";
    my $item_2 = "1.755";
    my $rnd_1 = (sprintf qq~%.2f~, $item_1);
    my $rnd_2 = (sprintf qq~%.2f~, $item_2);
    print "$rnd_1, $rnd_2";

The code above prints this result (system 10.1.5, perl 5.6.0):

    1.66, 1.75

But shouldn't it be:

    1.66, 1.76

or:

    1.65, 1.75

I'm no math wizard, so if someone could please take the time and tell what
I'm missing here I would very much appreciate it!

We all agreed this doesn't work well for finances and I've still not found a solution that is recommended for this problem. "Roll your own" seems to be the answer most often provided for this question.


With this in mind, I'd like to offer what I'm using now for review by those interested. This solution was given to me by Shawn McKinley. One of his goals was to make this portable so we can reuse it. I'll be using it on OS X 10.3. I won't even try to pretend I've deciphered all of it, but I'd like to know if anyone here can find anything wrong with this?

<code>
#!/usr/bin/perl -w

use strict;

my $item_1 = "1.655";
my $item_2 = "1.755";

print round($item_1),"\n";
print round($item_2);

sub round {
  my $t    = shift || 0;
  $t       = sprintf('%015i',int($t*1000));
  $t       =~ m/^\-?(\d*)(\d\d)(\d)$/;
  my($whole,$fraction,$rounder)=($1,$2,$3);
  $whole += 0;
  $fraction++ if($rounder > 4);
  if($fraction > 99) { $whole++; $fraction='00'; }
  return(($t=~/^\-/?'-':'').$whole.'.'.$fraction)
}
</code>

Also, if anyone has a better method, or even a different one, I'd love to see it.

Bill



Reply via email to