Using DecimalFormat to format big double numbers
java
Solution
The explanation as to why the parsed value is off by `19` lies in the how `double` values are represented, as IEEE floating-point numbers with 53 bits of precision. That is, for large values as you're inputting, the precision is actually greater than `1`. The method `Math.ulp`, for "unit in last place", gives the closest `double` values can be apart at the magnitude of its argument.
double d2 = 1234567879123456789d;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println(Math.ulp(d2));
System.out.println(df.format(d2));
This outputs
256.0
1234567879123456770
So, you get the closest `double` value to the number you type in the source code. Section 3.10.2 of the JLS covers `double` literals:
The elements of the types float and double are those values that can be represented using the IEEE 754 32-bit single-precision and 64-bit double-precision binary floating-point formats, respectively.
The details of proper input conversion from a Unicode string representation of a floating-point number to the internal IEEE 754 binary floating-point representation are described for the methods valueOf of class Float and class Double of the package java.lang.
And referring to `Double.valueOf` javadocs:
s is regarded as representing an exact decimal value in the usual "computerized scientific notation" or as an exact hexadecimal value; this exact numerical value is then conceptually converted to an "infinitely precise" binary value that is then rounded to type double by the usual round-to-nearest rule of IEEE 754 floating-point arithmetic [...]
Additionally, this value is still within the range of `long` values, which will still represent the integer value correctly.
long l2 = 1234567879123456789L;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println(df.format(l2));
This outputs
1234567879123456789
Problem
I am trying to use `DecimalFormat` to format double numbers to just print the number with 2 decimal places if it has fractional part else i want to print number as it is. When number is small, below code works fine but with big numbers, It's not working as expected. ``` DecimalFormat df = new DecimalFormat("#.##"); //have tried just # too double d1 = 56789d; System.out.println(df.format(d1)); //works fine - prints 56789 double d2 = 1234567879123456789d; System.out.println(df.format(d2)); // does not work ``` Second outputs `1234567879123456770` while I want `1234567879123456789`. For double values with decimal part, I just want to retain two decimal points. Any suggestions on what's going wrong?