Path: blob/master/src/java.base/share/classes/java/math/MathContext.java
41152 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved.27*/2829package java.math;30import java.io.*;3132/**33* Immutable objects which encapsulate the context settings which34* describe certain rules for numerical operators, such as those35* implemented by the {@link BigDecimal} class.36*37* <p>The base-independent settings are:38* <ol>39* <li>{@code precision}:40* the number of digits to be used for an operation; results are41* rounded to this precision42*43* <li>{@code roundingMode}:44* a {@link RoundingMode} object which specifies the algorithm to be45* used for rounding.46* </ol>47*48* @see BigDecimal49* @see RoundingMode50* @author Mike Cowlishaw51* @author Joseph D. Darcy52* @since 1.553*/5455public final class MathContext implements Serializable {5657/* ----- Constants ----- */5859// defaults for constructors60private static final int DEFAULT_DIGITS = 9;61private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;62// Smallest values for digits (Maximum is Integer.MAX_VALUE)63private static final int MIN_DIGITS = 0;6465// Serialization version66@java.io.Serial67private static final long serialVersionUID = 5579720004786848255L;6869/* ----- Public Properties ----- */70/**71* A {@code MathContext} object whose settings have the values72* required for unlimited precision arithmetic.73* The values of the settings are: {@code precision=0 roundingMode=HALF_UP}74*/75public static final MathContext UNLIMITED =76new MathContext(0, RoundingMode.HALF_UP);7778/**79* A {@code MathContext} object with a precision setting80* matching the precision of the IEEE 754-2019 decimal32 format, 7 digits, and a81* rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.82* Note the exponent range of decimal32 is <em>not</em> used for83* rounding.84*/85public static final MathContext DECIMAL32 =86new MathContext(7, RoundingMode.HALF_EVEN);8788/**89* A {@code MathContext} object with a precision setting90* matching the precision of the IEEE 754-2019 decimal64 format, 16 digits, and a91* rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.92* Note the exponent range of decimal64 is <em>not</em> used for93* rounding.94*/95public static final MathContext DECIMAL64 =96new MathContext(16, RoundingMode.HALF_EVEN);9798/**99* A {@code MathContext} object with a precision setting100* matching the precision of the IEEE 754-2019 decimal128 format, 34 digits, and a101* rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}.102* Note the exponent range of decimal64 is <em>not</em> used for103* rounding.104*/105public static final MathContext DECIMAL128 =106new MathContext(34, RoundingMode.HALF_EVEN);107108/* ----- Shared Properties ----- */109/**110* The number of digits to be used for an operation. A value of 0111* indicates that unlimited precision (as many digits as are112* required) will be used. Note that leading zeros (in the113* coefficient of a number) are never significant.114*115* <p>{@code precision} will always be non-negative.116*117* @serial118*/119final int precision;120121/**122* The rounding algorithm to be used for an operation.123*124* @see RoundingMode125* @serial126*/127final RoundingMode roundingMode;128129/* ----- Constructors ----- */130131/**132* Constructs a new {@code MathContext} with the specified133* precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding134* mode.135*136* @param setPrecision The non-negative {@code int} precision setting.137* @throws IllegalArgumentException if the {@code setPrecision} parameter is less138* than zero.139*/140public MathContext(int setPrecision) {141this(setPrecision, DEFAULT_ROUNDINGMODE);142return;143}144145/**146* Constructs a new {@code MathContext} with a specified147* precision and rounding mode.148*149* @param setPrecision The non-negative {@code int} precision setting.150* @param setRoundingMode The rounding mode to use.151* @throws IllegalArgumentException if the {@code setPrecision} parameter is less152* than zero.153* @throws NullPointerException if the rounding mode argument is {@code null}154*/155public MathContext(int setPrecision,156RoundingMode setRoundingMode) {157if (setPrecision < MIN_DIGITS)158throw new IllegalArgumentException("Digits < 0");159if (setRoundingMode == null)160throw new NullPointerException("null RoundingMode");161162precision = setPrecision;163roundingMode = setRoundingMode;164return;165}166167/**168* Constructs a new {@code MathContext} from a string.169*170* The string must be in the same format as that produced by the171* {@link #toString} method.172*173* <p>An {@code IllegalArgumentException} is thrown if the precision174* section of the string is out of range ({@code < 0}) or the string is175* not in the format created by the {@link #toString} method.176*177* @param val The string to be parsed178* @throws IllegalArgumentException if the precision section is out of range179* or of incorrect format180* @throws NullPointerException if the argument is {@code null}181*/182public MathContext(String val) {183boolean bad = false;184int setPrecision;185if (val == null)186throw new NullPointerException("null String");187try { // any error here is a string format problem188if (!val.startsWith("precision=")) throw new RuntimeException();189int fence = val.indexOf(' '); // could be -1190int off = 10; // where value starts191setPrecision = Integer.parseInt(val.substring(10, fence));192193if (!val.startsWith("roundingMode=", fence+1))194throw new RuntimeException();195off = fence + 1 + 13;196String str = val.substring(off, val.length());197roundingMode = RoundingMode.valueOf(str);198} catch (RuntimeException re) {199throw new IllegalArgumentException("bad string format");200}201202if (setPrecision < MIN_DIGITS)203throw new IllegalArgumentException("Digits < 0");204// the other parameters cannot be invalid if we got here205precision = setPrecision;206}207208/**209* Returns the {@code precision} setting.210* This value is always non-negative.211*212* @return an {@code int} which is the value of the {@code precision}213* setting214*/215public int getPrecision() {216return precision;217}218219/**220* Returns the roundingMode setting.221* This will be one of222* {@link RoundingMode#CEILING},223* {@link RoundingMode#DOWN},224* {@link RoundingMode#FLOOR},225* {@link RoundingMode#HALF_DOWN},226* {@link RoundingMode#HALF_EVEN},227* {@link RoundingMode#HALF_UP},228* {@link RoundingMode#UNNECESSARY}, or229* {@link RoundingMode#UP}.230*231* @return a {@code RoundingMode} object which is the value of the232* {@code roundingMode} setting233*/234235public RoundingMode getRoundingMode() {236return roundingMode;237}238239/**240* Compares this {@code MathContext} with the specified241* {@code Object} for equality.242*243* @param x {@code Object} to which this {@code MathContext} is to244* be compared.245* @return {@code true} if and only if the specified {@code Object} is246* a {@code MathContext} object which has exactly the same247* settings as this object248*/249public boolean equals(Object x){250if (!(x instanceof MathContext mc))251return false;252return mc.precision == this.precision253&& mc.roundingMode == this.roundingMode; // no need for .equals()254}255256/**257* Returns the hash code for this {@code MathContext}.258*259* @return hash code for this {@code MathContext}260*/261public int hashCode() {262return this.precision + roundingMode.hashCode() * 59;263}264265/**266* Returns the string representation of this {@code MathContext}.267* The {@code String} returned represents the settings of the268* {@code MathContext} object as two space-delimited words269* (separated by a single space character, <code>'\u0020'</code>,270* and with no leading or trailing white space), as follows:271* <ol>272* <li>273* The string {@code "precision="}, immediately followed274* by the value of the precision setting as a numeric string as if275* generated by the {@link Integer#toString(int) Integer.toString}276* method.277*278* <li>279* The string {@code "roundingMode="}, immediately280* followed by the value of the {@code roundingMode} setting as a281* word. This word will be the same as the name of the282* corresponding public constant in the {@link RoundingMode}283* enum.284* </ol>285* <p>286* For example:287* <pre>288* precision=9 roundingMode=HALF_UP289* </pre>290*291* Additional words may be appended to the result of292* {@code toString} in the future if more properties are added to293* this class.294*295* @return a {@code String} representing the context settings296*/297public java.lang.String toString() {298return "precision=" + precision + " " +299"roundingMode=" + roundingMode.toString();300}301302// Private methods303304/**305* Reconstitute the {@code MathContext} instance from a stream (that is,306* deserialize it).307*308* @param s the stream being read.309* @throws IOException if an I/O error occurs310* @throws ClassNotFoundException if a serialized class cannot be loaded311*/312@java.io.Serial313private void readObject(java.io.ObjectInputStream s)314throws java.io.IOException, ClassNotFoundException {315s.defaultReadObject(); // read in all fields316// validate possibly bad fields317if (precision < MIN_DIGITS) {318String message = "MathContext: invalid digits in stream";319throw new java.io.StreamCorruptedException(message);320}321if (roundingMode == null) {322String message = "MathContext: null roundingMode in stream";323throw new java.io.StreamCorruptedException(message);324}325}326327}328329330