| /* | |
| * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved. | |
| */ | |
| package java.math; | |
| import java.io.*; | |
| /** | |
| * Immutable objects which encapsulate the context settings which | |
| * describe certain rules for numerical operators, such as those | |
| * implemented by the {@link BigDecimal} class. | |
| * | |
| * <p>The base-independent settings are: | |
| * <ol> | |
| * <li>{@code precision}: | |
| * the number of digits to be used for an operation; results are | |
| * rounded to this precision | |
| * | |
| * <li>{@code roundingMode}: | |
| * a {@link RoundingMode} object which specifies the algorithm to be | |
| * used for rounding. | |
| * </ol> | |
| * | |
| * @see BigDecimal | |
| * @see RoundingMode | |
| * @spec https://standards.ieee.org/ieee/754/6210/ | |
| * IEEE Standard for Floating-Point Arithmetic | |
| * | |
| * @author Mike Cowlishaw | |
| * @author Joseph D. Darcy | |
| * @since 1.5 | |
| */ | |
| public final class MathContext implements Serializable { | |
| /* ----- Constants ----- */ | |
| // defaults for constructors | |
| private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP; | |
| // Smallest values for digits (Maximum is Integer.MAX_VALUE) | |
| private static final int MIN_DIGITS = 0; | |
| // Serialization version | |
| @java.io.Serial | |
| private static final long serialVersionUID = 5579720004786848255L; | |
| /* ----- 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} | |
| */ | |
| public static final MathContext UNLIMITED = | |
| new MathContext(0, RoundingMode.HALF_UP); | |
| /** | |
| * 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 (min exponent of -95, max | |
| * exponent of 96) 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 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 (min exponent of -383, max | |
| * exponent of 384) 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 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 decimal128 (min exponent of -6143, | |
| * max exponent of 6144) is <em>not</em> used for rounding. | |
| */ | |
| public static final MathContext DECIMAL128 = | |
| new MathContext(34, RoundingMode.HALF_EVEN); | |
| /* ----- Shared Properties ----- */ | |
| /** | |
| * The number of digits to be used for an operation. A value of 0 | |
| * indicates that unlimited precision (as many digits as are | |
| * required) will be used. Note that leading zeros (in the | |
| * coefficient of a number) are never significant. | |
| * | |
| * <p>{@code precision} will always be non-negative. | |
| * | |
| * @serial | |
| */ | |
| final int precision; | |
| /** | |
| * The rounding algorithm to be used for an operation. | |
| * | |
| * @see RoundingMode | |
| * @serial | |
| */ | |
| final RoundingMode roundingMode; | |
| /* ----- Constructors ----- */ | |
| /** | |
| * Constructs a new {@code MathContext} with the specified | |
| * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding | |
| * mode. | |
| * | |
| * @param setPrecision The non-negative {@code int} precision setting. | |
| * @throws IllegalArgumentException if the {@code setPrecision} parameter is less | |
| * than zero. | |
| */ | |
| public MathContext(int setPrecision) { | |
| this(setPrecision, DEFAULT_ROUNDINGMODE); | |
| } | |
| /** | |
| * Constructs a new {@code MathContext} with a specified | |
| * precision and rounding mode. | |
| * | |
| * @param setPrecision The non-negative {@code int} precision setting. | |
| * @param setRoundingMode The rounding mode to use. | |
| * @throws IllegalArgumentException if the {@code setPrecision} parameter is less | |
| * than zero. | |
| * @throws NullPointerException if the rounding mode argument is {@code null} | |
| */ | |
| public MathContext(int setPrecision, | |
| RoundingMode setRoundingMode) { | |
| if (setPrecision < MIN_DIGITS) | |
| throw new IllegalArgumentException("Digits < 0"); | |
| if (setRoundingMode == null) | |
| throw new NullPointerException("null RoundingMode"); | |
| precision = setPrecision; | |
| roundingMode = setRoundingMode; | |
| } | |
| /** | |
| * Constructs a new {@code MathContext} from a string. | |
| * | |
| * The string must be in the same format as that produced by the | |
| * {@link #toString} method. | |
| * | |
| * <p>An {@code IllegalArgumentException} is thrown if the precision | |
| * section of the string is out of range ({@code < 0}) or the string is | |
| * not in the format created by the {@link #toString} method. | |
| * | |
| * @param val The string to be parsed | |
| * @throws IllegalArgumentException if the precision section is out of range | |
| * or of incorrect format | |
| * @throws NullPointerException if the argument is {@code null} | |
| */ | |
| public MathContext(String val) { | |
| int setPrecision; | |
| if (val == null) | |
| throw new NullPointerException("null String"); | |
| try { // any error here is a string format problem | |
| if (!val.startsWith("precision=")) throw new RuntimeException(); | |
| int fence = val.indexOf(' '); // could be -1 | |
| int off = 10; // where value starts | |
| setPrecision = Integer.parseInt(val.substring(10, fence)); | |
| if (!val.startsWith("roundingMode=", fence+1)) | |
| throw new RuntimeException(); | |
| off = fence + 1 + 13; | |
| String str = val.substring(off, val.length()); | |
| roundingMode = RoundingMode.valueOf(str); | |
| } catch (RuntimeException re) { | |
| throw new IllegalArgumentException("bad string format"); | |
| } | |
| if (setPrecision < MIN_DIGITS) | |
| throw new IllegalArgumentException("Digits < 0"); | |
| // the other parameters cannot be invalid if we got here | |
| precision = setPrecision; | |
| } | |
| /** | |
| * Returns the {@code precision} setting. | |
| * This value is always non-negative. | |
| * | |
| * @return an {@code int} which is the value of the {@code precision} | |
| * setting | |
| */ | |
| public int getPrecision() { | |
| return precision; | |
| } | |
| /** | |
| * Returns the roundingMode setting. | |
| * This will be one of | |
| * {@link RoundingMode#CEILING}, | |
| * {@link RoundingMode#DOWN}, | |
| * {@link RoundingMode#FLOOR}, | |
| * {@link RoundingMode#HALF_DOWN}, | |
| * {@link RoundingMode#HALF_EVEN}, | |
| * {@link RoundingMode#HALF_UP}, | |
| * {@link RoundingMode#UNNECESSARY}, or | |
| * {@link RoundingMode#UP}. | |
| * | |
| * @return a {@code RoundingMode} object which is the value of the | |
| * {@code roundingMode} setting | |
| */ | |
| public RoundingMode getRoundingMode() { | |
| return roundingMode; | |
| } | |
| /** | |
| * Compares this {@code MathContext} with the specified | |
| * {@code Object} for equality. | |
| * | |
| * @param x {@code Object} to which this {@code MathContext} is to | |
| * be compared. | |
| * @return {@code true} if and only if the specified {@code Object} is | |
| * a {@code MathContext} object which has exactly the same | |
| * settings as this object | |
| */ | |
| public boolean equals(Object x){ | |
| if (!(x instanceof MathContext mc)) | |
| return false; | |
| return mc.precision == this.precision | |
| && mc.roundingMode == this.roundingMode; // no need for .equals() | |
| } | |
| /** | |
| * Returns the hash code for this {@code MathContext}. | |
| * | |
| * @return hash code for this {@code MathContext} | |
| */ | |
| public int hashCode() { | |
| return this.precision + roundingMode.hashCode() * 59; | |
| } | |
| /** | |
| * Returns the string representation of this {@code MathContext}. | |
| * The {@code String} returned represents the settings of the | |
| * {@code MathContext} object as two space-delimited words | |
| * (separated by a single space character, <code>'\u0020'</code>, | |
| * and with no leading or trailing white space), as follows: | |
| * <ol> | |
| * <li> | |
| * The string {@code "precision="}, immediately followed | |
| * by the value of the precision setting as a numeric string as if | |
| * generated by the {@link Integer#toString(int) Integer.toString} | |
| * method. | |
| * | |
| * <li> | |
| * The string {@code "roundingMode="}, immediately | |
| * followed by the value of the {@code roundingMode} setting as a | |
| * word. This word will be the same as the name of the | |
| * corresponding public constant in the {@link RoundingMode} | |
| * enum. | |
| * </ol> | |
| * <p> | |
| * For example: | |
| * <pre> | |
| * precision=9 roundingMode=HALF_UP | |
| * </pre> | |
| * | |
| * Additional words may be appended to the result of | |
| * {@code toString} in the future if more properties are added to | |
| * this class. | |
| * | |
| * @return a {@code String} representing the context settings | |
| */ | |
| public java.lang.String toString() { | |
| return "precision=" + precision + " " + | |
| "roundingMode=" + roundingMode.toString(); | |
| } | |
| // Private methods | |
| /** | |
| * Reconstitute the {@code MathContext} instance from a stream (that is, | |
| * deserialize it). | |
| * | |
| * @param s the stream being read. | |
| * @throws IOException if an I/O error occurs | |
| * @throws ClassNotFoundException if a serialized class cannot be loaded | |
| */ | |
| @java.io.Serial | |
| private void readObject(java.io.ObjectInputStream s) | |
| throws java.io.IOException, ClassNotFoundException { | |
| s.defaultReadObject(); // read in all fields | |
| // validate possibly bad fields | |
| if (precision < MIN_DIGITS) { | |
| String message = "MathContext: invalid digits in stream"; | |
| throw new java.io.StreamCorruptedException(message); | |
| } | |
| if (roundingMode == null) { | |
| String message = "MathContext: null roundingMode in stream"; | |
| throw new java.io.StreamCorruptedException(message); | |
| } | |
| } | |
| } |