programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
• Campbell Ritchie
• Ron McLeod
• Paul Clapham
• Jeanne Boyarsky
• Liutauras Vilda
Sheriffs:
• Rob Spoor
• Bear Bibeault
• Tim Cooke
Saloon Keepers:
• Tim Moores
• Stephan van Hulst
• Tim Holloway
• Carey Brown
• Piet Souris
Bartenders:
• Frits Walraven
• Himai Minh

# Float comparison riddle

Greenhorn
Posts: 11
• Number of slices to send:
Optional 'thank-you' note:
Hello,

I have this code and I coudn't understand the output of execution

The output is:

Are the same
Are different

Could anyone explain to me why ?

Regards,

Marshal
Posts: 72995
330
• 2
• Number of slices to send:
Optional 'thank-you' note:
Flating‑point arithmetic always entails slight imprecisions, and obviously the imprecision differs between 2.2f which is a float and 2.2 which is a double. Don't expect the == operator to give you accurate results with floating‑point numbers.
Numbers ending .5 can be accurately represented in binary, so they escape that problem.

Saloon Keeper
Posts: 6986
164
• Number of slices to send:
Optional 'thank-you' note:
If 2.2 were a float as well (as in "2.2f"), it would be considered the same value in terms of ==. But you should avoid comparing floats or doubles that way.

Saloon Keeper
Posts: 23729
161
• Number of slices to send:
Optional 'thank-you' note:

Tim Moores wrote:If 2.2 were a float as well (as in "2.2f"), it would be considered the same value in terms of ==. But you should avoid comparing floats or doubles that way.

Actually, that's wrong. First, because the "f" is already implied (in reality, it's "d") by virtue of having the manifest constant coded containing a decimal point.

The real reason that this fails is because fractions in floating-point are binary fractions, not decimal fractions. In binary, 1/2 (0.5) can be represented precisely, but 2/10 (0.2) cannot - it's the same as trying to represent 1/3 in decimal. You get a number that trails off into infinity (0.3333333...). But there's only a finite number of bits in a floating-point fraction, so you can only code an approximation.

In floating-point, comparing 0 to 0 is always guaranteed to succeed. Comparing 2 fractions where the value can be expressed by 1/x where x is a power of 2 or a polynomial of powers of 2 will succeed as long as the resulting value fits within the available number of bits.

For everything else, you're out of luck.

Which is why floating-point comparisons should always be a less/greater-than-or-equal and never exact equality or inequality unless the value you are testing for meets one of the criteria I just mentioned. Comparing == 0.0 is fine. Beyond that, you get progressively riskier.

Tim Moores
Saloon Keeper
Posts: 6986
164
• 1
• Number of slices to send:
Optional 'thank-you' note:

Tim Holloway wrote:

Tim Moores wrote:If 2.2 were a float as well (as in "2.2f"), it would be considered the same value in terms of ==. But you should avoid comparing floats or doubles that way.

Actually, that's wrong. First, because the "f" is already implied (in reality, it's "d") by virtue of having the manifest constant coded containing a decimal point.

Actually, it is correct.

https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.2 wrote:
A floating-point literal is of type float if it is suffixed with an ASCII letter F or f; otherwise its type is double and it can optionally be suffixed with an ASCII letter D or d (§4.2.3).

So 2.2 is a double, whereas 2.2f is a float, and using "if (f2 == 2.2f)" yields the result Mike was apparently looking for. But as we both said, it is risky and should be avoided.

Sheriff
Posts: 16278
271
• Number of slices to send:
Optional 'thank-you' note:
I'm with @Tim Moores on this.

Even with 0 values, you have to be careful when mixing floating point types.

Tim Holloway
Saloon Keeper
Posts: 23729
161
• Number of slices to send:
Optional 'thank-you' note:

Junilu Lacar wrote:I'm with @Tim Moores on this.

Even with 0 values, you have to be careful when mixing floating point types.

That's the difference between a zero value and a zero computation.

You are correct. A computation that yields "zero" should NOT be compared via equality tests. However, a value of zero is required to compare equal. Floating-point normalizes any number whose mantissa is zero to an internal value which has a zero exponent and sign. and thus compares equal internally on a bit-for-bit basis.

The expression sample you gave, however, computes 2.2f - 2.2d (again, manifest FP constants are double unless explicitly marked otherwise), and that's no more equal to zero than 0.3333 - 0.333333333333.

So it's perfectly fine to compare equality for absolutely zero, but NOT for fuzzy zero. There are cases where you know which you are dealing with and can safely test via equality to zero with impunity. Consider, for example, an "uninitialized" float or double variable. And there are many more cases when you cannot, so when in doubt...

And while we're at it, I should mention that comparing date/time values can be equally hazardous. In the case of timestamp-style values, different databases store different values of precision, so what you put in may not be what comes out!