Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Floating point issue

by vitoco (Hermit)
on Aug 12, 2016 at 21:50 UTC ( [id://1169672]=perlquestion: print w/replies, xml ) Need Help??

vitoco has asked for the wisdom of the Perl Monks concerning the following question:

If I try this oneliner:

perl -e "$a=-50.123456;for($i=0;$i<20;$i++){print qq!$i $a\n!;$a+=0.01}"

I get this:

0 -50.123456 1 -50.113456 2 -50.103456 3 -50.093456 4 -50.083456 5 -50.073456 6 -50.063456 7 -50.053456 8 -50.043456 9 -50.033456 10 -50.023456 11 -50.013456 12 -50.003456 13 -49.993456 14 -49.983456 15 -49.973456 16 -49.963456 17 -49.953456 18 -49.943456 19 -49.933456

But if I try this one:

perl -e "$a=-71.123456;for($i=0;$i<20;$i++){print qq!$i $a\n!;$a+=0.01}"

I get this:

0 -71.123456 1 -71.113456 2 -71.103456 3 -71.093456 4 -71.083456 5 -71.073456 6 -71.063456 7 -71.053456 8 -71.043456 9 -71.033456 10 -71.023456 11 -71.0134559999999 12 -71.0034559999999 13 -70.9934559999999 14 -70.9834559999999 15 -70.9734559999999 16 -70.9634559999999 17 -70.9534559999999 18 -70.9434559999999 19 -70.9334559999999

What's going on here?

Thanks!

Replies are listed 'Best First'.
Re: Floating point issue
by pryrt (Abbot) on Aug 12, 2016 at 21:57 UTC

      Actually not. Just googled it... Thanks for the hint.

      But what made me get confused was that it happened sometimes and wanted to know why.

        Depending on your starting value, sometimes the little tiny differences round to a value that Perl's default stringification will print differently than your expected precision, and sometimes they won't.

        If you want consistent precision in output, use sprintf or printf

Re: Floating point issue
by Marshall (Canon) on Aug 12, 2016 at 22:26 UTC
    Binary floating point cannot represent 0.01 from base 10 exactly, close but not exact. Here is an example of rounding the printout using printf():

    Update: I got a suggestion to make my warning about the use of $a and $b more prominent. $a and $b are Perl reserved variables and are used by sort amoungst other functions. Users should not use these variables. Use $x or $y or something else instead. Following my own advice, I changed from $a to $x below. Here the OP's use of $a "worked", but it is a bad habit to get into.

    #!usr/bin/perl use strict; use warnings; print "====float =======\n"; my $x=-50.123456; for my $i (0...19) { printf "%i\t%.3f\n", $i,$x; $x+=0.01; } $x=-71.123456; for my $i (0...19) { printf "%i\t%.3f\n", $i,$x; $x+=0.01; } __END__ ====float ======= 0 -50.123 1 -50.113 2 -50.103 3 -50.093 4 -50.083 5 -50.073 6 -50.063 7 -50.053 8 -50.043 9 -50.033 10 -50.023 11 -50.013 12 -50.003 13 -49.993 14 -49.983 15 -49.973 16 -49.963 17 -49.953 18 -49.943 19 -49.933 0 -71.123 1 -71.113 2 -71.103 3 -71.093 4 -71.083 5 -71.073 6 -71.063 7 -71.053 8 -71.043 9 -71.033 10 -71.023 11 -71.013 12 -71.003 13 -70.993 14 -70.983 15 -70.973 16 -70.963 17 -70.953 18 -70.943 19 -70.933
    Update: added similar comment above and changed $a to $x.
    Here it is ok, but $a and $b are reserved Perl variables and shouldn't be used by users. Use $x or $y instead.
Re: Floating point issue
by Laurent_R (Canon) on Aug 13, 2016 at 07:44 UTC
    Hi,

    consider this simple one-liner where the output should presumably be 0:

    $ perl -e 'print .1 + .2 - .3, "\n"' 5.55111512312578e-17
    A very small number, indeed, but not zero.

    BTW, the same in the Perl 6 REPL:

    > say .1 + .2 - .3 0
Re: Floating point issue
by vitoco (Hermit) on Aug 13, 2016 at 21:53 UTC

    Thank you, guys.

    I'll use sprintf as a workaround...

      A more accurate alternative might be to use integer arithmetic:
      $ perl -E '$c = -71123456; for my $i (0..19) {say $c/1000000; $c += 10 +000}' -71.123456 -71.113456 -71.103456 -71.093456 -71.083456 -71.073456 -71.063456 -71.053456 -71.043456 -71.033456 -71.023456 -71.013456 -71.003456 -70.993456 -70.983456 -70.973456 -70.963456 -70.953456 -70.943456 -70.933456
      You might also consider using the arbitrary big rational number module (Math::BigRat) or possibly the big float module (Math::BigFloat).

      Math::BigRat is accurate because it basically does integer arithmetic under the hood.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1169672]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-23 14:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found