Search code examples
javadoublebigdecimalfloating-point-precisionrounding-error

Why are certain doubles automatically rounded when printed to the console?


Say I have the following code:

double factor;
double num = 4.35;
BigDecimal y = new BigDecimal(num);
BigDecimal n = new BigDecimal(factor);
BigDecimal asBigDecimal = y.multiply(n);
double asDouble = num * factor;
System.out.println("Double: " + asDouble + "\tBigDecimal: " + asBigDecimal);

This is what happens when I set factor to each of the following:

factor = 1:    Double: 4.35 BigDecimal: 4.3499999999999996447286321199499070644378662109375
factor = 10:   Double: 43.5 BigDecimal: 43.4999999999999964472863211994990706443786621093750
factor = 100:  Double: 434.99999999999994   BigDecimal: 434.9999999999999644728632119949907064437866210937500
factor = 1000: Double: 4350.0   BigDecimal: 4349.9999999999996447286321199499070644378662109375000

Also, when I run System.out.print(4.35 / 10); as a separate program, I get 0.43499999999999994 in the console. Why is it that multiplying by 1, 10, and 1000 give rounded answers (as doubles) in the console? I understand the basics of floating point precision and that 4.35 should not be able to be expressed exactly in binary form, so why is 4.35 printed to the console (asDouble)? Why doesn't multiplying by 100 or dividing by 10 automatically round?


Solution

  • There are a couple of things going on. First, there is rounding in binary, and then, there is rounding in decimal.

    Look at the binary representations of those BigDecimal values (I used my Decimal/Binary Converter):

    factor = 1:    100.0101100110011001100110011001100110011001100110011         (52 bits)
    factor = 10:   101011.011111111111111111111111111111111111111111111111       (53 bits)
    factor = 100:  110110010.11111111111111111111111111111111111111111111011     (56 bits)
    factor = 1000: 1000011111101.1111111111111111111111111111111111111111100111  (59 bits)
    

    The results for factors 1 and 10 aren't rounded in binary; they are <= 53 bits. Rounded to 17 decimal digits for printing they are 4.35 and 43.5, respectively.

    The results for factors 100 and 1000 ARE rounded. The factor 100 result is rounded down to this value, since bit 54 is 0:

       factor = 100:  110110010.11111111111111111111111111111111111111111111        (53 bits)
    

    In decimal, that is 434.99999999999994315658113919198513031005859375. Rounded to 17 digits it's 434.99999999999994.

    The factor 1000 result is rounded up to this value, since bits 54 and beyond are > 1/2 ULP:

    factor = 1000: 1000011111110
    

    That is 4350.