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?
Just use %. 2f as the format specifier. This will make the Java printf format a double to two decimal places. /* Code example to print a double to two decimal places with Java printf */ System.
We can use DecimalFormat("0.00") to ensure the number always round to 2 decimal places.
2f syntax tells Java to return your variable (value) with 2 decimal places (. 2) in decimal representation of a floating-point number (f) from the start of the format specifier (%).
To limit the number of digits up to 2 places after the decimal, the toFixed() method is used. The toFixed() method rounds up the floating-point number up to 2 places after the decimal. Parameters: String: The floating-point number in the string format that is to be parsed.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With