Skip to content

Commit 1dafbe3

Browse files
committed
8294539: Augment discussion of equivalence relations on floating-point values
Reviewed-by: psandoz, smarks
1 parent b2e86a6 commit 1dafbe3

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

src/java.base/share/classes/java/lang/Double.java

+64-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
*
5959
* IEEE 754 floating-point values include finite nonzero values,
6060
* signed zeros ({@code +0.0} and {@code -0.0}), signed infinities
61-
* {@linkplain Double#POSITIVE_INFINITY positive infinity} and
61+
* ({@linkplain Double#POSITIVE_INFINITY positive infinity} and
6262
* {@linkplain Double#NEGATIVE_INFINITY negative infinity}), and
6363
* {@linkplain Double#NaN NaN} (not-a-number).
6464
*
@@ -116,12 +116,13 @@
116116
* <p>To provide the appropriate semantics for {@code equals} and
117117
* {@code compareTo} methods, those methods cannot simply be wrappers
118118
* around {@code ==} or ordered comparison operations. Instead, {@link
119-
* Double#equals equals} defines NaN arguments to be equal to each
120-
* other and defines {@code +0.0} to <em>not</em> be equal to {@code
121-
* -0.0}, restoring reflexivity. For comparisons, {@link
122-
* Double#compareTo compareTo} defines a total order where {@code
123-
* -0.0} is less than {@code +0.0} and where a NaN is equal to itself
124-
* and considered greater than positive infinity.
119+
* Double#equals equals} uses <a href=#repEquivalence> representation
120+
* equivalence</a>, defining NaN arguments to be equal to each other,
121+
* restoring reflexivity, and defining {@code +0.0} to <em>not</em> be
122+
* equal to {@code -0.0}. For comparisons, {@link Double#compareTo
123+
* compareTo} defines a total order where {@code -0.0} is less than
124+
* {@code +0.0} and where a NaN is equal to itself and considered
125+
* greater than positive infinity.
125126
*
126127
* <p>The operational semantics of {@code equals} and {@code
127128
* compareTo} are expressed in terms of {@linkplain #doubleToLongBits
@@ -143,6 +144,62 @@
143144
* elements of a {@link java.util.SortedSet SortedSet} or as keys of a
144145
* {@link java.util.SortedMap SortedMap}.
145146
*
147+
* <p>Comparing numerical equality to various useful equivalence
148+
* relations that can be defined over floating-point values:
149+
*
150+
* <dl>
151+
* <dt><a id=fpNumericalEq><i>numerical equality</i></a> ({@code ==}
152+
* operator): (<em>Not</em> an equivalence relation)</dt>
153+
* <dd>Two floating-point values represent the same extended real
154+
* number. The extended real numbers are the real numbers augmented
155+
* with positive infinity and negative infinity. Under numerical
156+
* equality, {@code +0.0} and {@code -0.0} are equal since they both
157+
* map to the same real value, 0. A NaN does not map to any real
158+
* number and is not equal to any value, including itself.
159+
* </dd>
160+
*
161+
* <dt><i>bit-wise equivalence</i>:</dt>
162+
* <dd>The bits of the two floating-point values are the same. This
163+
* equivalence relation for {@code double} values {@code a} and {@code
164+
* b} is implemented by the expression
165+
* <br>{@code Double.doubleTo}<code><b>Raw</b></code>{@code LongBits(a) == Double.doubleTo}<code><b>Raw</b></code>{@code LongBits(b)}<br>
166+
* Under this relation, {@code +0.0} and {@code -0.0} are
167+
* distinguished from each other and every bit pattern encoding a NaN
168+
* is distinguished from every other bit pattern encoding a NaN.
169+
* </dd>
170+
*
171+
* <dt><i><a id=repEquivalence>representation equivalence</a></i>:</dt>
172+
* <dd>The two floating-point values represent the the same IEEE 754
173+
* <i>datum</i>. In particular, for {@linkplain #isFinite(double)
174+
* finite} values, the sign, {@linkplain Math#getExponent(double)
175+
* exponent}, and significand components of the
176+
* floating-point values are the same. Under this relation:
177+
* <ul>
178+
* <li> {@code +0.0} and {@code -0.0} are distinguished from each other.
179+
* <li> every bit pattern encoding a NaN is considered equivalent to each other
180+
* <li> positive infinity is equivalent to positive infinity; negative
181+
* infinity is equivalent to negative infinity.
182+
* </ul>
183+
* Expressions implementing this equivalence relation include:
184+
* <ul>
185+
* <li>{@code Double.doubleToLongBits(a) == Double.doubleToLongBits(b)}
186+
* <li>{@code Double.valueOf(a).equals(Double.valueOf(b))}
187+
* <li>{@code Double.compare(a, b) == 0}
188+
* </ul>
189+
* Note that representation equivalence is often an appropriate notion
190+
* of equivalence to test the behavior of {@linkplain StrictMath math
191+
* libraries}.
192+
* </dd>
193+
* </dl>
194+
*
195+
* For two binary floating-point values {@code a} and {@code b}, if
196+
* neither of {@code a} and {@code b} is zero or NaN, then the three
197+
* relations numerical equality, bit-wise equivalence, and
198+
* representation equivalence of {@code a} and {@code b} have the same
199+
* {@code true}/{@code false} value. In other words, for binary
200+
* floating-point values, the three relations only differ if at least
201+
* one argument is zero or NaN.
202+
*
146203
* @jls 4.2.3 Floating-Point Types, Formats, and Values
147204
* @jls 4.2.4. Floating-Point Operations
148205
* @jls 15.21.1 Numerical Equality Operators == and !=

src/java.base/share/classes/java/math/BigDecimal.java

+7
Original file line numberDiff line numberDiff line change
@@ -3087,6 +3087,10 @@ public BigDecimal stripTrailingZeros() {
30873087
30883088
* @apiNote
30893089
* Note: this class has a natural ordering that is inconsistent with equals.
3090+
* The behavior of comparing the result of this method for
3091+
* equality to 0 is analogous to checking the <a
3092+
* href="{@docRoot}/java.base/java/lang/Double.html#fpNumericalEq">numerical
3093+
* equality</a> of {@code double} values.
30903094
*
30913095
* @param val {@code BigDecimal} to which this {@code BigDecimal} is
30923096
* to be compared.
@@ -3179,6 +3183,9 @@ else if (ys != INFLATED)
31793183
* HALF_UP)} which evaluates to 0.7 and <br>
31803184
* {@code new BigDecimal("2.00").divide(BigDecimal.valueOf(3),
31813185
* HALF_UP)} which evaluates to 0.67.
3186+
* The behavior of this method is analogous to checking the <a
3187+
* href="{@docRoot}/java.base/java/lang/Double.html#repEquivalence">representation
3188+
* equivalence</a> of {@code double} values.
31823189
*
31833190
* @param x {@code Object} to which this {@code BigDecimal} is
31843191
* to be compared.

0 commit comments

Comments
 (0)