views:

7912

answers:

5

I have a primitive float and I need as a primitive double. Simply casting the float to double gives me weird extra precision. For example:

float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375

However, if instead of casting, I output the float as a string, and parse the string as a double, I get what I want:

System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35

Is there a better way than to go to String and back?

+14  A: 

It's not that you're actually getting extra precision - it's that the float didn't accurately represent the number you were aiming for originally. The double is representing the original float accurately; toString is showing the "extra" data which was already present.

For example (and these numbers aren't right, I'm just making things up) support you had:

float f = 0.1F;
double d = f;

Then the value of f might be exactly 0.100000234523. d will have exactly the same value, but when you convert it to a string it will "trust" that it's accurate to a higher precision, so won't round off as early, and you'll see the "extra digits" which were already there, but hidden from you.

When you convert to a string and back, you're ending up with a double value which is closer to the string value than the original float was - but that's only good if you really believe that th string value is what you really wanted.

Are you sure that float/double are the appropriate types to use here instead of BigDecimal? If you're trying to use numbers which have precise decimal values (e.g. money), then BigDecimal is a more appropriate type IMO.

Jon Skeet
I think your answer best describes the reason for my problem. My solution might 'work' but I realize now I'm sort of asking the wrong question. Thanks.
Steve Armstrong
I've got the same issue in .NET and this explains it very well, thank you.
Evgeny
+1  A: 

Use a BigDecimal instead of float/double. There are a lot of numbers which can't be represented as binary floating point (for example, 0.1 ). So you either must always round the result to a known precision or use BigDecimal.

See http://en.wikipedia.org/wiki/Floating_point for more information.

Aaron Digulla
A: 

Floats, by nature, are imprecise and always have neat rounding "issues". If precision is important then you might consider refactoring your application to use Decimal or BigDecimal.

Yes, floats are computationally faster than decimals because of the on processor support. However, do you want fast or accurate?

Chris Lively
Decimal arithmetic is inexact too. (e.g. 1 / 3 * 3 == 0.9999999999999999999999999999) It is, of course, better for representing exact **decimal** quantities like money, but for physical measurements it has no advantage.
dan04
+6  A: 
erickson
+1 Great answer with quote from documentation.
Evgeny
A: 

For information this comes under Item 48 - Avoid float and double when exact values are required, of Effective Java 2nd edition by Joshua Bloch. This book is jam packed with good stuff and definitely worth a look.

mR_fr0g