This week's book giveaway is in the Design forum. We're giving away four copies of Building Microservices and have Sam Newman on-line! See this thread for details.

anybody could please explain why is it that System.out.println() when displaying a double rounds the value off or truncates the value?

say I have a code.

double d = 0.10000000000000000111512312578; System.out.println(d);

the output is "0.1" and not the exact value?

in the JLS, it provides some explanation, but if I understood it corretly, it seems that there is not definite format whether to display as "0.1" or the exact "0.10000000000000000111512312578" as long as it is the closest value to the double value..

Forgive me if I'm wrong, but is the answer to this not that you are simply running out of precision in the "double"?

My understanding is that there are about 15 decimal digits of precision in a "double" and about 7 decimal digits of precision in a "float". Your number simply has too many zeros between the "tenths" and the rest of the number.

Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.

Bang on, Peter. (not an instruction! ) Use java.math.BigDecimal if you want more precision.

Jules

kenneth ga
Greenhorn

Joined: Aug 05, 2004
Posts: 9

posted

0

thanks, you're probably right.

but, is there a rule in the toString(double) that says, the value will be rounded off when it's over the supported precision of "double"?

I can't find any or I could not understand what the Double.toString(double) really says about this one. Which I think is the one that is responsible in displaying the "double" string.

could anyone please spare some time for me on this one?

I really appreciate your help.

thanks.

Julian Kennedy
Ranch Hand

Joined: Aug 02, 2004
Posts: 823

posted

0

I recently posted this in another thread:

That's the vagaries of floating point representation and arithmetic for you. The reason for the strangeness is that the internal representation is in binary. The sign, mantissa (bit before the 'E') and exponent (bit after the 'E') are split across the 32 bits of a float or the 64 bits of a double.

With only so many bits to work with there is a limit on the precision (number of significant figures, I suppose) that can be achieved. The more bits you have, the better the precision. Think about it. 1.1 in binary is 1.5 in decimal; 1.11 is 1.75; 1.111 is 1.875 and so on. Say you want to represent the decimal number 0.999 in binary: you can never do it exactly as 1.???1 in binary is always going to be 1.???5 in decimal.

Scary huh?! It's official that computers can't count, and they're running the systems that take care of your bank balance and keep the planes in the air!

Hope that's informative.

Does that shed any further light on it for you? As Peter said, there's no room in 64 bits (a double) for more than 15 digits of precision. The actual conversion to String and/or printing is irrelevant. The poor old double is left with no choice as she has eaten all the pies! (is full)

Jules

kenneth ga
Greenhorn

Joined: Aug 05, 2004
Posts: 9

posted

0

i'm beginning to understand and the way seems clearer

however, i tried to look at the actual implementation of Double.toString(double) and in there, it manipulates the value of the "double" to be representable as "string". However, a double value of "0.1" which has no actual decimal representation is being manipulated to be representable in its closest value. It just so happen that the implementation makes it to "0.1" string. But the implementation can display "0.02" or "0.234" as a representation of that double 0.1 value.

what i mean is, that it can represent any "string" value since it is a string not an actual "double" value, the one that is outputted by System.out.println().

I am understanding it right?

I hope you get my point.

thanks.

Julian Kennedy
Ranch Hand

Joined: Aug 02, 2004
Posts: 823

posted

0

Sorry Kenneth, I don't really see what you're getting at. If the value in a double named point_one is 0.1D then why would Double.toString(point_one) return 0.02 or 0.234?

The moral of the story is that if you require very precise representations of floating point number then don't use float and double; use java.math.BigDecimal instead.

Jules

Peter Chase
Ranch Hand

Joined: Oct 30, 2001
Posts: 1970

posted

0

While we're here, is it not true that Double.toString() is really only for debugging use?

If you are planning to put a floating-point number (float or double) in front of an end-user, you should carefully format it according to the needs of the application. The java.text.DecimalFormat class may help here.

One generally should not put the full number of digits in front of the user, either. This is because floating-point maths accumulates round-off errors, so one or more of the least-significant decimal digits are inaccurate and should not be displayed.

How many digits are accurate depends on the types of floating-point operations that have been performed. If it's just a few additions and subtractions, then all but the last digit are likely to be correct. But if you've been doing iterative numerical calculations, logarithms, exponentiation, trig functions ... then many digits will be inaccurate. In some cases, errors can accumulate to the point where the whole answer is useless, though this rarely happens outside the confines of serious mathematical computing.

For the above reasons, floating-point should not be used for fixed-point calculations, like currency calculations.

kenneth ga
Greenhorn

Joined: Aug 05, 2004
Posts: 9

posted

0

Originally posted by Julian Kennedy: Sorry Kenneth, I don't really see what you're getting at. If the value in a double named point_one is 0.1D then why would Double.toString(point_one) return 0.02 or 0.234?

hello jules, this is exactly my point that i want to be cleared out. yes, indeed why should "0.1" be printed out as "0.02"? but if it is printed as "0.10", is this a bug?

the specs of Double.toString(double), if i understood it correctly, does not specify on how many number of decimal places should be printed, so i can display "0.1000000000000000000000000000000" instead of just "0.1".