there's this annoying little conversion problem that is getting in my way.
I was under the impression that a widening conversion from a float to a double primitive (which happens implicitly without a cast) would conserve the original value completely. This however doesn't seem to be the case. Here's an example:
The result is:
The problem is that when I explicitly want to store the value 3.02 in a float and it gets converted to a double, this double variable does not contain exactly what was in the float.
One thought is that double is not able to hold the 3.02 value exactly, but this is disproven by the 5th and 6th line of code where the conversion is done via a String object (how resource-wasting can you get ). Via this method the double does contain the value originally intended.
Another idea is that the original float variable didn't really contain the 3.02 but rather an approximation, and that this approximation shows up as a real intended value when the conversion to double happens.
Net result is that I have an intended value in the form of a float and I can only get this value exactly in a double by doing the conversion via a String object which is incredibly resource wasting... Apparently the widening conversion between float and double isn't as preserving as I thought.
I don't think this problem is just because of the conversion. By their natures, float and double are both imprecise representation for numbers. This is inherent in both of them. Usually it isn't much of a problem, but occassionaly when you manipulate floats or doubles, you get this kind of behavior.
To avoid these issues, I rarely ever use float. If I need decimal places, I almost always use double since it provides a larger precision. However, in some cases, it actually make sense to use int or long because these are exact. For example, if you are writing a financial calculator, you can use an int to store monetary values in pennies (assuming a U.S. locale). You just have to make sure to format it into the expected dollars and cents when you output it for the user.
d==f returns true, so they're actually the same number.
seems like you've got a problem at hand. and yeah, even wrapping is unable to preserve the values. must have got something to with the interna; representation.
let me see the JLS ok, here it is "Conversions widening from float to double in strictfp expressions also preserve the numeric value exactly; however, such conversions that are not strictfp may lose information about the overall magnitude of the converted value." there lies the answer, make it strictfp! easy to say, but ive tried out the possibilities, doesn't seem to work though. try try try [ October 24, 2005: Message edited by: Akshay Kiran ]
"It's not enough that we do our best; sometimes we have to do<br />what's required."<br /> <br />-- Sir Winston Churchill
Raf Van de Plas
Joined: Aug 29, 2001
Since d == f is true, it seems that the internal representations of both variables are still behaving as expected. However, you might argue that the f is implicitly converted to a double and you're actually checking equality between two doubles.
My guess is that the difference shows up in the code that displays the value of a variable as a numeric value. When showing a float, this code probably figures out that 3.02 was meant (as its the closest possible value in all possible floats). When showing a double this code finds the even closer value of 3.0199999809265137 (not present in the 'world of float') and shows it.
If this hunch is correct then this entire situation might be as close to correct as possible on the machine level, but might introduce an intuitive 'gotcha'.
If this is a correct assumption then there's no real problem with using widening conversion in Java between float and double, but it does imply to remember that what you see is not necessarily what you've got (just very close to it).
d == f is only true because to do the comparison, the float must be converted to a double. Since the value of d is itself already just f converted to a double, you would expect them to be the same. That doesn't mean that f and d both have exactly the same value: they don't.
In any case, there are two rules you must always follow when using any floating point numbers:
1) Never compare for exact equality.
2) Never display an unformatted number.
All those extra digits are irrelevant. The number you're looking at is the closest binary rational number to the real number 3.2 using 32 or 64 bits; that's the best the (IEEE standard) hardware can do, and that's what Java does. If you want the value rounded to the nearest 1/10, then you should use DecimalFormat and format it that way.