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

Simple addition/subtraction not working

by vptimmy (Initiate)
on Dec 01, 2011 at 21:59 UTC ( #941175=perlquestion: print w/ replies, xml ) Need Help??
vptimmy has asked for the wisdom of the Perl Monks concerning the following question:

I have been banging my head against the wall and thought i should find some help. This is some really basic addition and subtraction that should equal 0.

#!/usr/bin/perl use strict; my $first_num = '-3500.78'; my $second_num = '-1057.12'; my $third_num = '5100'; my $fourth_num = '-681'; my $fifth_num = '46.3'; my $sixth_num = '46.3'; my $seventh_num = '46.3'; print "FIRST NUMBER = $first_num\n"; print "SECOND NUMBER = $second_num\n"; print "THIRD NUMBER = $third_num\n"; print "FOURTH NUMBER = $fourth_num\n"; print "FIFTH NUMBER = $fifth_num\n"; print "SIXTH NUMBER = $sixth_num\n"; print "SEVENTH NUMBER = $seventh_num\n"; my $total = $first_num + $second_num + $third_num + $fourth_num + $fif +th_num + $sixth_num + $seventh_num; print "TOTAL = $total\n\n"; #BREAK IT DOWN my $first_total = $first_num + $second_num; print "#1: $first_num + $second_num = $first_total\n"; my $second_total = $first_total + $third_num; print "#2: $first_total + $third_num = $second_total\n"; my $third_total = $second_total + $fourth_num; print "#3: $second_total + $fourth_num = $third_total\n"; my $fourth_total = $third_total + $fifth_num; print "#4: $third_total + $fifth_num = $fourth_total\n"; my $fifth_total = $fourth_total + $sixth_num; print "#5: $fourth_total - $sixth_num = $fifth_total\n"; my $sixth_total = $fifth_total + $seventh_num; print "#6: $fifth_total + $seventh_num = $sixth_total\n";

Here are the results of the program:

FIRST NUMBER = -3500.78
SECOND NUMBER = -1057.12
THIRD NUMBER = 5100
FOURTH NUMBER = -681
FIFTH NUMBER = 46.3
SIXTH NUMBER = 46.3
SEVENTH NUMBER = 46.3
TOTAL = 3.5527136788005e-13

#1: -3500.78 + -1057.12 = -4557.9 (correct)
#2: -4557.9 + 5100 = 542.1 (correct)
#3: 542.1 + -681 = -138.9 (correct)
#4: -138.9 + 46.3 = -92.5999999999996 (WHAT?)
#5: -92.5999999999996 - 46.3 = -46.2999999999996 (WHAT?)
#6: -46.2999999999996 + 46.3 = 3.5527136788005e-13 (WHAT?)

I have a program that goes out and adds a budget up and kept encountering this problem. I decided to simplify it and break it down to try to find where the issue is. Been a long day and think my brains are just leaking out of my head. Thanks in advance, -vptimmy

Comment on Simple addition/subtraction not working
Download Code
Re: Simple addition/subtraction not working
by JavaFan (Canon) on Dec 01, 2011 at 22:09 UTC
    Most floating point numbers cannot be represented by a native float. You're suffering from rounding errors.
Re: Simple addition/subtraction not working
by toolic (Chancellor) on Dec 01, 2011 at 22:09 UTC
Re: Simple addition/subtraction not working
by chromatic (Archbishop) on Dec 01, 2011 at 22:10 UTC

    This is never obvious until you encounter it, but computers represent floating-point numbers in an interesting way. perlfaq4's "Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?" says:

    Internally, your computer represents floating-point numbers in binary. Digital (as in powers of two) computers cannot store all numbers exactly. Some real numbers lose precision in the process. This is a problem with how computers store numbers and affects all computer languages, not just Perl.

    It also points to the PDF What Every Computer Scientist Should Know About Floating-Point Arithmetic.

    One of the easiest solutions is to store monetary values as pennies (or whatever the fractional amount of your local currency is) to avoid floating point values altogether.

    (As a side note, if you're declaring numeric values, you're better off writing my $first_num = -3500.78; without the quotes; there's no need to make them string values if you're going to treat them as numerics.)


    Improve your skills with Modern Perl: the free book.

Re: Simple addition/subtraction not working
by choroba (Abbot) on Dec 01, 2011 at 22:13 UTC
Re: Simple addition/subtraction not working
by GrandFather (Cardinal) on Dec 01, 2011 at 22:15 UTC

    If you are dealing with a budget work in cents and the issue will go away. The problem is that most decimal fractions can't be represented as finite binary fractions and computers tend to have finite representations for numbers.

    There are various other ways to deal with the problem depending on your application. But if you are dealing with money to the nearest cent then working in cents avoids the problem entirely because you are then working with integers which are exactly represented in binary or decimal.

    True laziness is hard work
      Don't make the assumption every currency has cents. Some currencies use mills, some don't have subunits, some don't have mills, but they do have mill prices (pumped gas lately?), and some (digital only) currencies use 5 digits after the decimal point.

        Even with 5 decimal digits, a 64-bit int can represent 184 trillion, which in dollars is roughly 3 times the entire worlds gross domestic product for 2010. Should be good enough for the average Internet reseller for a few years.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

Re: Simple addition/subtraction not working
by ikegami (Pope) on Dec 01, 2011 at 23:18 UTC
    78/100, 12/100 and 3/10 are all periodic numbers in binary (like 1/3 is in decimal). As such, they cannot be accurately represented by floating point numbers.
Re: Simple addition/subtraction not working
by InfiniteSilence (Curate) on Dec 08, 2011 at 01:01 UTC
    perl -e 'use Math::BigFloat; my $x = Math::BigFloat->new(q|-138.9|); p +rint $x->badd(q|46.3|);'
    Returns
    -92.6

    Celebrate Intellectual Diversity

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://941175]
Approved by toolic
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (10)
As of 2014-12-19 13:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (83 votes), past polls