Summary
-------
Add a discussion of how IEEE 754 decimal arithmetic relates to `BigDecimal` arithmetic. Make some exceptional cases more explicit.
Problem
-------
The `BigDecimal` class does not discuss how it differs from the decimal arithmetic standardized in IEEE 754.
Solution
--------
Update `BigDecimal` and other classes in `java.math` accordingly.
Specification
-------------
diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java
index 7257a6f349e..5bb8a58184e 100644
--- a/src/java.base/share/classes/java/math/BigDecimal.java
+++ b/src/java.base/share/classes/java/math/BigDecimal.java
@@ -37,7 +37,7 @@
/**
* Immutable, arbitrary-precision signed decimal numbers. A
* {@code BigDecimal} consists of an arbitrary precision integer
- * <i>unscaled value</i> and a 32-bit integer <i>scale</i>. If zero
+ * <i>{@linkplain unscaledValue() unscaled value}</i> and a 32-bit integer <i>{@linkplain scale() scale}</i>. If zero
* or positive, the scale is the number of digits to the right of the
* decimal point. If negative, the unscaled value of the number is
* multiplied by ten to the power of the negation of the scale. The
@@ -220,6 +220,63 @@
* Comparable}, {@link java.util.SortedMap} or {@link
* java.util.SortedSet} for more information.
*
+ * <h2>Relation to IEEE 754 Decimal Arithmetic</h2>
+ *
+ * Starting with its 2008 revision, the <cite>IEEE 754 Standard for
+ * Floating-point Arithmetic</cite> has covered decimal formats and
+ * operations. While there are broad similarities in the decimal
+ * arithmetic defined by IEEE 754 and by this class, there are notable
+ * differences as well. The fundamental similarity shared by {@code
+ * BigDecimal} and IEEE 754 decimal arithmetic is the conceptual
+ * operation of computing the mathematical infinitely precise real
+ * number value of an operation and then mapping that real number to a
+ * representable decimal floating-point value under a <em>rounding
+ * policy</em>. The rounding policy is called a {@linkplain
+ * RoundingMode rounding mode} for {@code BigDecimal} and called a
+ * rounding-direction attribute in IEEE 754-2019. When the exact value
+ * is not representable, the rounding policy determines which of the
+ * two representable decimal values bracketing the exact value is
+ * selected as the computed result. The notion of a <em>preferred
+ * scale/preferred exponent</em> is also shared by both systems.
+ *
+ * <p>For differences, IEEE 754 includes several kinds of values not
+ * modeled by {@code BigDecimal} including negative zero, signed
+ * infinities, and NaN (not-a-number). IEEE 754 defines formats, which
+ * are parameterized by base (binary or decimal), number of digits of
+ * precision, and exponent range. A format determines the set of
+ * representable values. Most operations accept as input one or more
+ * values of a given format and produce a result in the same format.
+ * A {@code BigDecimal}'s {@linkplain scale() scale} is equivalent to
+ * negating an IEEE 754 value's exponent. {@code BigDecimal} values do
+ * not have a format in the same sense; all values have the same
+ * possible range of scale/exponent and the {@linkplain
+ * unscaledValue() unscaled value} has arbitrary precision. Instead,
+ * for the {@code BigDecimal} operations taking a {@code MathContext}
+ * parameter, if the {@code MathContext} has a nonzero precision, the
+ * set of possible representable values for the result is determined
+ * by the precision of the {@code MathContext} argument. For example
+ * in {@code BigDecimal}, if a nonzero three-digit number and a
+ * nonzero four-digit number are multiplied together in the context of
+ * a {@code MathContext} object having a precision of three, the result
+ * will have three digits (assuming no overflow or underflow, etc.).
+ *
+ * <p>The rounding policies implemented by {@code BigDecimal}
+ * operations indicated by {@linkplain RoundingMode rounding modes}
+ * are a proper superset of the IEEE 754 rounding-direction
+ * attributes.
+
+ * <p>{@code BigDecimal} arithmetic will most resemble IEEE 754
+ * decimal arithmetic if a {@code MathContext} corresponding to an
+ * IEEE 754 decimal format, such as {@linkplain MathContext#DECIMAL64
+ * decimal64} or {@linkplain MathContext#DECIMAL128 decimal128} is
+ * used to round all starting values and intermediate operations. The
+ * numerical values computed can differ if the exponent range of the
+ * IEEE 754 format being approximated is exceeded since a {@code
+ * MathContext} does not constrain the scale of {@code BigDecimal}
+ * results. Operations that would generate a NaN or exact infinity,
+ * such as dividing by zero, throw an {@code ArithmeticException} in
+ * {@code BigDecimal} arithmetic.
+ *
* @see BigInteger
* @see MathContext
* @see RoundingMode
@@ -1681,7 +1738,7 @@ public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
*
* @param divisor value by which this {@code BigDecimal} is to be divided.
* @throws ArithmeticException if the exact quotient does not have a
- * terminating decimal expansion
+ * terminating decimal expansion, including dividing by zero
* @return {@code this / divisor}
* @since 1.5
* @author Joseph D. Darcy
@@ -1745,7 +1802,7 @@ public BigDecimal divide(BigDecimal divisor) {
* @throws ArithmeticException if the result is inexact but the
* rounding mode is {@code UNNECESSARY} or
* {@code mc.precision == 0} and the quotient has a
- * non-terminating decimal expansion.
+ * non-terminating decimal expansion,including dividing by zero
* @since 1.5
*/
public BigDecimal divide(BigDecimal divisor, MathContext mc) {
diff --git a/src/java.base/share/classes/java/math/MathContext.java b/src/java.base/share/classes/java/math/MathContext.java
index 028ede34de6..5c759666eee 100644
--- a/src/java.base/share/classes/java/math/MathContext.java
+++ b/src/java.base/share/classes/java/math/MathContext.java
@@ -69,39 +69,39 @@
/* ----- Public Properties ----- */
/**
- * A {@code MathContext} object whose settings have the values
- * required for unlimited precision arithmetic.
- * The values of the settings are:
- * <code>
- * precision=0 roundingMode=HALF_UP
- * </code>
+ * A {@code MathContext} object whose settings have the values
+ * required for unlimited precision arithmetic.
+ * The values of the settings are: {@code precision=0 roundingMode=HALF_UP}
*/
public static final MathContext UNLIMITED =
new MathContext(0, RoundingMode.HALF_UP);
/**
- * A {@code MathContext} object with a precision setting
- * matching the IEEE 754R Decimal32 format, 7 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
+ * A {@code MathContext} object with a precision setting
+ * matching the precision of the IEEE 754-2019 decimal32 format, 7 digits, and a
+ * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.
+ * Note the exponent range of decimal32 is <em>not</em> used for
+ * rounding.
*/
public static final MathContext DECIMAL32 =
new MathContext(7, RoundingMode.HALF_EVEN);
/**
- * A {@code MathContext} object with a precision setting
- * matching the IEEE 754R Decimal64 format, 16 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
+ * A {@code MathContext} object with a precision setting
+ * matching the precision of the IEEE 754-2019 decimal64 format, 16 digits, and a
+ * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.
+ * Note the exponent range of decimal64 is <em>not</em> used for
+ * rounding.
*/
public static final MathContext DECIMAL64 =
new MathContext(16, RoundingMode.HALF_EVEN);
/**
- * A {@code MathContext} object with a precision setting
- * matching the IEEE 754R Decimal128 format, 34 digits, and a
- * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
- * IEEE 754R default.
+ * A {@code MathContext} object with a precision setting
+ * matching the precision of the IEEE 754-2019 decimal128 format, 34 digits, and a
+ * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.
+ * Note the exponent range of decimal64 is <em>not</em> used for
+ * rounding.
*/
public static final MathContext DECIMAL128 =
new MathContext(34, RoundingMode.HALF_EVEN);
diff --git a/src/java.base/share/classes/java/math/RoundingMode.java b/src/java.base/share/classes/java/math/RoundingMode.java
index de7c33e5392..92e9463c932 100644
--- a/src/java.base/share/classes/java/math/RoundingMode.java
+++ b/src/java.base/share/classes/java/math/RoundingMode.java
@@ -29,7 +29,7 @@
package java.math;
/**
- * Specifies a <i>rounding behavior</i> for numerical operations
+ * Specifies a <i>rounding policy</i> for numerical operations
* capable of discarding precision. Each rounding mode indicates how
* the least significant returned digit of a rounded result is to be
* calculated. If fewer digits are returned than the digits needed to
@@ -89,7 +89,7 @@
*
* @apiNote
* Five of the rounding modes declared in this class correspond to
- * rounding direction attributes defined in the <cite>IEEE Standard
+ * rounding-direction attributes defined in the <cite>IEEE Standard
* for Floating-Point Arithmetic</cite>, IEEE 754-2019. Where present,
* this correspondence will be noted in the documentation of the
* particular constant.
@@ -137,7 +137,7 @@
* Rounding mode to round towards zero. Never increments the digit
* prior to a discarded fraction (i.e., truncates). Note that this
* rounding mode never increases the magnitude of the calculated value.
- * This mode corresponds to the IEEE 754-2019 rounding
+ * This mode corresponds to the IEEE 754-2019 rounding-direction
* attribute roundTowardZero.
*
*<p>Example:
@@ -168,7 +168,7 @@
* result is positive, behaves as for {@code RoundingMode.UP};
* if negative, behaves as for {@code RoundingMode.DOWN}. Note
* that this rounding mode never decreases the calculated value.
- * This mode corresponds to the IEEE 754-2019 rounding
+ * This mode corresponds to the IEEE 754-2019 rounding-direction
* attribute roundTowardPositive.
*
*<p>Example:
@@ -199,7 +199,7 @@
* result is positive, behave as for {@code RoundingMode.DOWN};
* if negative, behave as for {@code RoundingMode.UP}. Note that
* this rounding mode never increases the calculated value.
- * This mode corresponds to the IEEE 754-2019 rounding
+ * This mode corresponds to the IEEE 754-2019 rounding-direction
* attribute roundTowardNegative.
*
*<p>Example:
@@ -232,7 +232,7 @@
* fraction is ≥ 0.5; otherwise, behaves as for
* {@code RoundingMode.DOWN}. Note that this is the rounding
* mode commonly taught at school.
- * This mode corresponds to the IEEE 754-2019 rounding
+ * This mode corresponds to the IEEE 754-2019 rounding-direction
* attribute roundTiesToAway.
*
*<p>Example:
@@ -301,7 +301,7 @@
* chiefly used in the USA. This rounding mode is analogous to
* the rounding policy used for {@code float} and {@code double}
* arithmetic in Java.
- * This mode corresponds to the IEEE 754-2019 rounding
+ * This mode corresponds to the IEEE 754-2019 rounding-direction
* attribute roundTiesToEven.
*
*<p>Example: