Atom Feed SITE FEED   ADD TO GOOGLE READER

Floating point equality

In working through some bugs in Harmony, one thing that's been consistent is my surprise. Floating point's special values slightly complicate things...

Negative Zero
Floats and doubles have two distinct representations for nada: 0.0F and -0.0F.

NaN
Rather than risking an ArithmeticException, floats model error values natively. There are multiple binary representations of NaN; use floatToRawIntBits() to see yours. Most developers will prefer floatToIntBits(), which returns the same bits for all NaNs.


There's also a variety of ways to store floating point values. Each representation has its own merits and drawbacks:
Primitives
Fast, memory efficient, and nonnull.

In wrappers
Classes like Float and Double can be used in collections. Wrapper variables are nullable and implement convenient APIs from Number and Comparable.

In buffers
FloatBuffer and DoubleBuffer store nonnull values in bulk. Buffers provide direct access to data in files and streams.


Unfortunately, the interplay between the values and their representation is imperfect. Consider how equality differs by value and representation.
ValuesPrimitives
==
In wrappers
Object.equals()
In buffers
Buffer.equals()
-0.0, +0.0equalnot equalequal
NaN, NaNnot equalequalequal

This behaviour is inconsistent but I suspect the differences weren't introduced lightly. Primitive types need to work in expressions so that 5/0 doesn't equal 0/0. But wrapper types need to work in collections so that Set.add() is consistent with Set.contains().

On their own, exotic values and exotic representations both make sense. But since complexity is the N×M product of the feature set, our result is inevitable pain. Would be language designers should prefer fewer representations and fewer special values.
I can't remember ever reading or hearing about "-0.0", and must admit I don't get it. I guess I'll be studying the JLS today.
Floating point is (or perhaps should be) largely the domain of applied mathematicians, engineers and scientists. We don't find the special values quite so surprising. They were not of course invented by Java, but are inherited from the much older IEEE 754 specification.
The classic use of -0 involves the conformal mapping of an aerofoil. +0 represents the flow over the top surface of the wing, while -0 corresponds to flow over the lower surface.

http://www.grc.nasa.gov/WWW/K-12/airplane/map.html

(complete with a Java applet for the example).