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

I am setting a variable $finalamount = $v_amount - ($plbamt) with v_amount = -683.12 and $plbamt = -683.12. This should result in $finalamount = 0 but it results in 1.13686837721616e-013 can anyone tell me why this is?

Replies are listed 'Best First'.
Re: subtraction issue
by choroba (Cardinal) on Jan 24, 2017 at 21:47 UTC
Re: subtraction issue
by syphilis (Archbishop) on Jan 24, 2017 at 22:28 UTC
    This should result in $finalamount = 0

    If you printf "%a\n", $v_amount; and printf "%a\n", $plbamount; (for which you need to be running perl-5.22.0 or later) you'll get to see the exact value of the 2 variables (in hex).

    If they turn out to be the same && $finalamount is not zero, then you have a seriously broken perl.

    Cheers,
    Rob

      Anonymous: Previous to Perl version 5.22.0, you can use a format like '%0.20f'.


      Give a man a fish:  <%-{-{-{-<

        Previous to Perl version 5.22.0, you can use a format like '%0.20f'

        Yes, I think that's a good enough replacement for most purposes - and a useful addition to my post.

        However, it's not guaranteed to give you the exact base 10 value stored in the double - whereas %a will give you the exact (base 16) value.

        Cheers,
        Rob
Re: subtraction issue
by hippo (Archbishop) on Jan 25, 2017 at 09:07 UTC

    Disproven:

    #!/usr/bin/perl use strict; use warnings; use Test::More tests => 1; my $v_amount = -683.12; my $plbamt = -683.12; my $finalamount = $v_amount - ($plbamt); # Why have brackets here, OP? is ($finalamount, 0, 'Nothing to see here');
    can anyone tell me why this is?

    Yes, it is because at least one of $v_amount or $plbamt does not have the value which you think it has. See the links the other monks have given you regarding imprecision of floating point numbers in computing.

Re: subtraction issue
by LanX (Saint) on Jan 25, 2017 at 17:46 UTC
    > This should result in $finalamount = 0 but it results in 1.13686837721616e-013 can anyone tell me why this is?

    you most likely have a calculation resulting in a fraction of 0.12 after the point which is 3/25 and 25=5^2 can't be coded without loss in a binary system.

    Additionally Perl does some DWIM magic to hide minor errors, such that a printed 0.12 is not necessarily == 0.12 .

    solution:

    To calculate dollars "accurately" with 2 decimal places, you need
    to calculate right from the beginning in cents as integers!

    So just calculate with integers in the desired accuracy and shift the decimal point afterwards!

    from Humans have too many fingers

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!