49.95 + 0.45 = 50.400000000000006

Tuesday, September 25. 2007

Have a look at the following simple piece of code:
public class WeirdDouble {
    public static void main(String args[]) {
        Double result = 49.95 + 0.44;
        System.out.println(result);
        result = 49.95 + 0.45;
        System.out.println(result);
        result = 49.95 + 0.46;
        System.out.println(result);
        result = 49.95 + 0.47;
        System.out.println(result);
    }
}
Theres nothing complicated going on here. Just a few simple addition of Of course you would expect the following output:
50.39
50.40
50.41
50.42
Wrong! The output will look like this.
50.39
50.400000000000006
50.410000000000004
50.42

Oh my god! Another calculation bug in an Intel processor? A bug in the Java VM? Or is it the Linux Kernel that is misbehaving? Wrong! In fact the result is perfectly OK. In fact it's even a defined behaviour for floating point numbers (see IEEE 754) and this will also happen in a similar C program.

To understand this result you have to think in binary. Floating point numbers are approximated by binary numbers. There is no exact representation possible, just an approximation to the next closest representation of a floating point number in binary. As a simple float is represented in single precision by a 32 bit number there are cases, when 49.95 is in fact something like 49.950000000000004, which got rounded to 49.95. When you add another float the imprecision introduced by the approximation sums up and in some cases the result will be different than expected.

On the web you can find various examples covering the same issue. A detailed discussion can be found on Suns Java forum.

Update (2007-27-09):

Joel Spolsky has a very nice explanation of this effect in the context of the Excel 2007 calculation bug.


Twitter Bookmark 49.95 + 0.45 = 50.400000000000006  at del.icio.us Facebook Google Bookmarks Digg 49.95 + 0.45 = 50.400000000000006 Bookmark 49.95 + 0.45 = 50.400000000000006  at YahooMyWeb

Trackbacks


Trackback specific URI for this entry
    No Trackbacks

Comments


    #1 Carsten Aulbert on 09/25/07 at 09:00 PM [Reply]
    *Well, wildly known by low-level programmers ;-)

    For the C (without the fancy ++ or #) people, try to compile and run the following:

    #include<stdlib.h>
    #include<stdio.h>

    int main (void)
    {
    float a = 0.;
    int b = 0;
    while ( a < 1. ) {
    printf ( "%d %g %g\n", b, b*0.00001, a );
    b++;
    a+= 0.00001;
    }
    return 0;
    }

    The final line of this is *shudder*:

    99901 0.99901 0.999999

    If you are interested in more details, please read:

    http://docs.sun.com/source/806-3568/ncg_goldberg.html

    If you think: "Nah, I'm using Excel all the time, this can never happen to me!" then read this:

    http://it.slashdot.org/it/07/09/24/2339203.shtml

    Have fun!
    #1.1 Carsten Schlipf on 09/25/07 at 09:18 PM [Reply]
    *Thank you very much for the further examples. Well, me as high level programmer just expects things to work like intended ;-)

Add Comment

HTML-Tags will be converted to Entities.
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA