RFR: JDK-8257086: Clarify differences between {Float, Double}.equals and ==

Joe Darcy darcy at openjdk.java.net
Thu Jan 28 07:17:39 UTC 2021

On Thu, 10 Dec 2020 01:32:24 GMT, Stuart Marks <smarks at openjdk.org> wrote:

> Great, let me know if you'd like me to provide some text for any particular topics in this area.

Before sending out another iteration in code, there the draft javadoc text of a discussion at the end of the class-level discussion of java.lang.Double:

 * <h2><a id=equivalenceRelation>Floating-point Equality, Equivalence,
 * and Comparison</a></h2>
 * IEEE 754 floating-point values include finite nonzero values,
 * signed zeros ({@code +0.0} and {@code -0.0}), signed infinities
 * {@linkplain Double#POSITIVE_INFINITY positive infinity} and
 * {@linkplain Double#NEGATIVE_INFINITY negative infinity}), and
 * {@linkplain Double#NaN NaN} (not-a-number).
 * <p>An <em>equivalence relation</em> on a set of values is a boolean
 * relation on pairs of values that is reflexive, symmetric, and
 * transitive. A set can have multiple equivalence relations defined
 * for it. For example, {@link java.util.HashMap HashMap} compares
 * keys in the set of objects using the equivalence relation of {@link
 * Object#equals Object.equals} while {@link java.util.IdentityHashMap
 * IdentityHashMap} compares keys in the set of objects using the
 * equivalence relation of reference equality.
 * <p>For floating-point values to be used in data structures like
 * sets and maps, the {@linkplain Double#equals equals} or {@linkplain
 * Double#compareTo comparison} method must satisfy the usual
 * requirements of being an equivalence relation or analogous
 * requirement for comparison methods. However, surprisingly, the
 * built-in {@code ==} operation on floating-point values does
 * <em>not</em> implement an equivalence relation. Despite not
 * defining an equivalence relation, the semantics of the IEEE 754
 * {@code ==} operator were deliberately designed to meet other needs
 * of numerical computation. There are two exceptions where the
 * properties of an equivalence relations are not satisfied by {@code
 * ==} on floating-point values:
 * <ul>
 * <li>If {@code v1} and {@code v2} are both NaN, then {@code v1
 * == v2} has the value {@code false}. Therefore, for two NaN
 * arguments the <em>reflexive</em> property of an equivalence
 * relation is <em>not</em> satisfied by the {@code ==} operator.
 * <li>If {@code v1} represents {@code +0.0} while {@code v2}
 * represents {@code -0.0}, or vice versa, then {@code v1 == v2} has
 * the value {@code true} even though {@code +0.0} and {@code -0.0}
 * are distinguishable under various floating-point operations. For
 * example, {@code 1.0/+0.0} evaluates to positive infinity while
 * {@code 1.0/-0.0} evaluates to <em>negative</em> infinity and
 * positive infinity and negative infinity are neither equal to each
 * other nor equivalent to each other.
 * </ul>
 * <p>For ordered comparisons using the built-in comparison operator
 * ({@code <}, {@code <=}, etc.), NaN values have another anomalous
 * situation: a NaN is neither less than, greater than, nor equal to
 * any value, including itself. This means the <em>trichotomy of
 * comparison</em> does <em>not</em> hold.
 * <p>To provide the appropriate semantics for {@code equals} and {@code
 * compareTo} methods, those methods cannot simply to wrappers around
 * {@code ==} or ordered comparison operations. Instead, {@link
 * Double#equals equals} defines NaN arguments to be equal to each
 * other and defines {@code +0.0} to <em>not</em> be equal to {@code
 * -0.0}, restoring reflexivity. For comparisons, {@link
 * Double#compareTo compareTo} defines a total order where {@code
 * -0.0} is less than {@code +0.0} and where a NaN is equal to itself
 * and considered greater than positive infinity.
 * <p>The operational semantics of {@code equals} and {@code
 * compareTo} are expressed in terms of {@linkplain doubleToLongBigs
 * bit-wise converting} the floating-point values to integral values 
 * <p>The <em>natural ordering</em> implemented by {@link compareTo
 * compareTo} is {@linkplain Comparable consistent with equals}; that
 * is values are only reported as equal by {@code equals} if {@code
 * compareTo} on those objects returns zero.
 * @jls 4.2.3 Floating-Point Types, Formats, and Values
 * @jls 4.2.4. Floating-Point Operations
 * @jls 15.21.1 Numerical Equality Operators == and !=




PR: https://git.openjdk.java.net/jdk/pull/1699

More information about the core-libs-dev mailing list