Details

Type: CSR

Status: Closed

Priority: P4

Resolution: Approved

Fix Version/s: 17

Component/s: corelibs

Labels:None

Subcomponent:

Compatibility Risk:minimal

Compatibility Risk Description:Mostly an informative spec clarification; explicitly mentions divide by zero throwing exceptions.

Interface Kind:Java API

Scope:SE
Description
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, arbitraryprecision signed decimal numbers. A
* {@code BigDecimal} consists of an arbitrary precision integer
 * <i>unscaled value</i> and a 32bit integer <i>scale</i>. If zero
+ * <i>{@linkplain unscaledValue() unscaled value}</i> and a 32bit 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
+ * Floatingpoint 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 floatingpoint value under a <em>rounding
+ * policy</em>. The rounding policy is called a {@linkplain
+ * RoundingMode rounding mode} for {@code BigDecimal} and called a
+ * roundingdirection attribute in IEEE 7542019. 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 (notanumber). 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 threedigit number and a
+ * nonzero fourdigit 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 roundingdirection
+ * 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
 * nonterminating decimal expansion.
+ * nonterminating 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 7542019 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 7542019 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 7542019 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
+ * roundingdirection attributes defined in the <cite>IEEE Standard
* for FloatingPoint Arithmetic</cite>, IEEE 7542019. 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 7542019 rounding
+ * This mode corresponds to the IEEE 7542019 roundingdirection
* 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 7542019 rounding
+ * This mode corresponds to the IEEE 7542019 roundingdirection
* 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 7542019 rounding
+ * This mode corresponds to the IEEE 7542019 roundingdirection
* 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 7542019 rounding
+ * This mode corresponds to the IEEE 7542019 roundingdirection
* 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 7542019 rounding
+ * This mode corresponds to the IEEE 7542019 roundingdirection
* attribute roundTiesToEven.
*
*<p>Example:
Attachments
Issue Links
 csr of

JDK8261366 Add discussion of IEEE 754 to BigDecimal
 Resolved