Big Moose Saloon
 Search | Java FAQ | Recent Topics Register / Login

# does Double.toString() always return exact value?

zheng li
Ranch Hand

Joined: Jun 16, 2009
Posts: 56
BigDecimal a = new BigDecimal(2.3);
System.out.println(a);
OUTPUT:
2.29999999999999982236431605997495353221893310546875

a = new BigDecimal(String.valueOf(2.3));
System.out.println(a);
OUTPUT:
2.3

is it true that Double.toString() always returns exact value?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 34560

13
No.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 34560

13
Have you read the documentation for Double#toString()?
Look at our FAQ (no 20). It tells you about nearest value to distinguish a double from its adjacent value. It might be better to ask "does Double.toString() ever return exact value?"
zheng li
Ranch Hand

Joined: Jun 16, 2009
Posts: 56
thank you.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 34560

13
You're welcome
zheng li
Ranch Hand

Joined: Jun 16, 2009
Posts: 56
double d = 2.3;
double d1 = 2.29999999999999982236431605997495353221893310546875;
System.out.println(String.format("%.100f", d));
System.out.println(String.format("%.100f", d1));
System.out.println(new BigDecimal(d));
System.out.println(new BigDecimal(d1));
// according to IEEE 754, 2.29999999999999937827510620991233736276626586914062
double d2 = 2.2999999999999996;
// according to IEEE 754, 2.29999999999999982236431605997495353221893310546875
double d3 = 2.2999999999999997;
System.out.println(String.format("%.100f", d2));
System.out.println(String.format("%.100f", d3));

OUTPUT:
2.3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2.3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2.29999999999999982236431605997495353221893310546875
2.29999999999999982236431605997495353221893310546875
2.2999999999999994000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2.3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

according to IEEE 754,
the really value of 2.3 stored in memory should be 2.29999999999999982236431605997495353221893310546875.
why are the first 2 lines 2.3?

it seems that java stores floating-point types in IEEE 754 format, but does some kind of rounding off when using them.
does anyone know why java deals with double this way?
is there any specification about it?

Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 2916

4
zheng li wrote:it seems that java stores floating-point types in IEEE 754 format, but does some kind of rounding off when using them.

Correct.

zheng li wrote:does anyone know why java deals with double this way?

I would guess the creators of Java wanted the numbers to print in a more human-friendly format than what you are expecting.

zheng li wrote:is there any specification about it?

Yes, if we break your question into two parts:

If d = 2.3:

1) Why does System.out.println(d) print "2.3"?

Because println(d) ends up being specified by Double.toString(d) which says:
How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double.

In the case of 2.3, no other possible double is closer to 2.3 than the one you call d1 is, so "2.3" is sufficient to uniquely identify that value - even if it doesn't look exactly the same.

2) Why does String.format("%.100f", d) return "2.3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"?

Format specifiers are described under the API for java.util.Formatter. The part about what the ".100" part does is here:
The width is the minimum number of characters to be written to the output. If the length of the converted value is less than the width then the output will be padded by ' ' (\u0020') until the total number of characters equals the width. The padding is on the left by default. If the '-' flag is given, then the padding will be on the right.

Basically, all we need to get from this is that padding does not add any actual mathematical precision to the calculation - it just adds zeroes to what you would have gotten without the padding. Since the println(d) prints "2.3", all we get with padding is to add zeroes to it.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 2916

4
Here's something that may help:

This shows the possible double values in the neighborhood of 2.3:

When we write "2.3" that gets translated into the double closest to 2.3, which is on the middle line. When that value is printed, it is printed with the minimum number of digits after the decimal point which will still uniquely identify that value. And so "2.3" is sufficient, because no other double is closer to 2.3 than the value shown in the middle line.
zheng li
Ranch Hand

Joined: Jun 16, 2009
Posts: 56
thank you guys.
now i finally understand what "adjacent values" means.

I agree. Here's the link: http://aspose.com/file-tools

subject: does Double.toString() always return exact value?