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?
Double precision numbers are accurate up to sixteen decimal places but after calculations have been done there may be some rounding errors to account for. In theory this should affect no more than the last significant digit but in practice it is safer to rely upon fewer decimal places.
The doubleValue() method of Java Float class returns a double value corresponding to this Float Object by widening the primitive values or in simple words by directly converting it to double via doubleValue() method .
double has 2x more precision than float. float is a 32-bit IEEE 754 single precision Floating Point Number – 1 bit for the sign, 8 bits for the exponent, and 23* for the value. float has 7 decimal digits of precision.
Remember, by default floating-point numbers are double in Java, if you want to store them into float variables, you need to either cast them explicitly or suffixed them using the 'f' or 'F' characters.
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) suppose 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 the 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.
I find converting to the binary representation easier to grasp this problem.
float f = 0.27f; double d2 = (double) f; double d3 = 0.27d; System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f))); System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2))); System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3)));
You can see the float is expanded to the double by adding 0s to the end, but that the double representation of 0.27 is 'more accurate', hence the problem.
111110100010100011110101110001 11111111010001010001111010111000100000000000000000000000000000 11111111010001010001111010111000010100011110101110000101001000
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