develooper Front page | perl.perl5.porters | Postings from September 2000

Re: [ID 20000917.004] Internal floating-point rounding error?

From:
Tom Christiansen
Date:
September 17, 2000 18:20
Subject:
Re: [ID 20000917.004] Internal floating-point rounding error?
Message ID:
13170.969240024@chthon
>This is a bug report for perl from Philip.Andrew@stanfordalumni.org,
>generated with the help of perlbug 1.28 running under perl v5.6.0.

>-----------------------------------------------------------------
>[Please enter your report here]

>I get strange results running the following Perl stub:

>    printf "%04d\n", $ARGV[0]/$ARGV[1];

>Results:

>    # Command Run	=>	Output
>    # -----------		------
>    stub.pl 0.55 0.01   =>      0055
>    stub.pl 0.56 0.01   =>      0056
>    stub.pl 0.57 0.01   =>      0056	<== HUH?
>    stub.pl 0.58 0.01   =>      0057	<== HUH?
>    stub.pl 0.59 0.01   =>      0058	<== HUH?
>    stub.pl 0.60 0.01   =>      0060
>    stub.pl 0.61 0.01   =>      0061
>    stub.pl 0.055 0.001 =>      0055
>    stub.pl 0.056 0.001 =>      0056
>    stub.pl 0.057 0.001 =>      0057
>    stub.pl 0.058 0.001 =>      0058
>    stub.pl 0.059 0.001 =>      0058	<== HUH?
>    stub.pl 0.060 0.001 =>      0060
>    stub.pl 0.061 0.001 =>      0061

>I can avoid this round-off error by changing the 'printf' to

>    printf "%04d\n", ($ARGV[0]/$ARGV[1])+($ARGV[1]/10);

>(adding 1/10 of my resolution to the number), but what's the
>point -- the round-off is supposed to be correct, isn't it?

Define "correct" and define "round" -- both within the rules and
regulations of binary floating-point arithmetic.

I'm afraid Perl has no bug.  It just doesn't do what you want
it to do.  

There is no exact representation of 0.56:

      printf "%.20f\n", .57
    0.56999999999999995115

Now watch:

      printf "%.20f\n", .57 * 100
    56.99999999999999289457

What would the int()eger truncation be there?  Find the decimal
place, and discard.  Thus:

      printf "%d\n", .57 * 100
    56

      print int(.57 * 100)
    56

Now, why does:

      print (.57 * 100)
    57

Because print's default output format for numbers is such that 
you get some sort of rounding.  

Of course, this is still not always what you want (IEEE's required
alternating "rounding" behavior on the halves, for example).

--tom



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About