jaroslav@1258: /* jaroslav@1258: * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. jaroslav@1258: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1258: * jaroslav@1258: * This code is free software; you can redistribute it and/or modify it jaroslav@1258: * under the terms of the GNU General Public License version 2 only, as jaroslav@1258: * published by the Free Software Foundation. Oracle designates this jaroslav@1258: * particular file as subject to the "Classpath" exception as provided jaroslav@1258: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1258: * jaroslav@1258: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1258: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1258: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1258: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1258: * accompanied this code). jaroslav@1258: * jaroslav@1258: * You should have received a copy of the GNU General Public License version jaroslav@1258: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1258: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1258: * jaroslav@1258: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1258: * or visit www.oracle.com if you need additional information or have any jaroslav@1258: * questions. jaroslav@1258: */ jaroslav@1258: jaroslav@1258: /* jaroslav@1258: * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved. jaroslav@1258: */ jaroslav@1258: jaroslav@1258: package java.math; jaroslav@1258: import java.io.*; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Immutable objects which encapsulate the context settings which jaroslav@1258: * describe certain rules for numerical operators, such as those jaroslav@1258: * implemented by the {@link BigDecimal} class. jaroslav@1258: * jaroslav@1258: *

The base-independent settings are: jaroslav@1258: *

    jaroslav@1258: *
  1. {@code precision}: jaroslav@1258: * the number of digits to be used for an operation; results are jaroslav@1258: * rounded to this precision jaroslav@1258: * jaroslav@1258: *
  2. {@code roundingMode}: jaroslav@1258: * a {@link RoundingMode} object which specifies the algorithm to be jaroslav@1258: * used for rounding. jaroslav@1258: *
jaroslav@1258: * jaroslav@1258: * @see BigDecimal jaroslav@1258: * @see RoundingMode jaroslav@1258: * @author Mike Cowlishaw jaroslav@1258: * @author Joseph D. Darcy jaroslav@1258: * @since 1.5 jaroslav@1258: */ jaroslav@1258: jaroslav@1258: public final class MathContext implements Serializable { jaroslav@1258: jaroslav@1258: /* ----- Constants ----- */ jaroslav@1258: jaroslav@1258: // defaults for constructors jaroslav@1258: private static final int DEFAULT_DIGITS = 9; jaroslav@1258: private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP; jaroslav@1258: // Smallest values for digits (Maximum is Integer.MAX_VALUE) jaroslav@1258: private static final int MIN_DIGITS = 0; jaroslav@1258: jaroslav@1258: // Serialization version jaroslav@1258: private static final long serialVersionUID = 5579720004786848255L; jaroslav@1258: jaroslav@1258: /* ----- Public Properties ----- */ jaroslav@1258: /** jaroslav@1258: * A {@code MathContext} object whose settings have the values jaroslav@1258: * required for unlimited precision arithmetic. jaroslav@1258: * The values of the settings are: jaroslav@1258: * jaroslav@1258: * precision=0 roundingMode=HALF_UP jaroslav@1258: * jaroslav@1258: */ jaroslav@1258: public static final MathContext UNLIMITED = jaroslav@1258: new MathContext(0, RoundingMode.HALF_UP); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * A {@code MathContext} object with a precision setting jaroslav@1258: * matching the IEEE 754R Decimal32 format, 7 digits, and a jaroslav@1258: * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the jaroslav@1258: * IEEE 754R default. jaroslav@1258: */ jaroslav@1258: public static final MathContext DECIMAL32 = jaroslav@1258: new MathContext(7, RoundingMode.HALF_EVEN); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * A {@code MathContext} object with a precision setting jaroslav@1258: * matching the IEEE 754R Decimal64 format, 16 digits, and a jaroslav@1258: * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the jaroslav@1258: * IEEE 754R default. jaroslav@1258: */ jaroslav@1258: public static final MathContext DECIMAL64 = jaroslav@1258: new MathContext(16, RoundingMode.HALF_EVEN); jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * A {@code MathContext} object with a precision setting jaroslav@1258: * matching the IEEE 754R Decimal128 format, 34 digits, and a jaroslav@1258: * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the jaroslav@1258: * IEEE 754R default. jaroslav@1258: */ jaroslav@1258: public static final MathContext DECIMAL128 = jaroslav@1258: new MathContext(34, RoundingMode.HALF_EVEN); jaroslav@1258: jaroslav@1258: /* ----- Shared Properties ----- */ jaroslav@1258: /** jaroslav@1258: * The number of digits to be used for an operation. A value of 0 jaroslav@1258: * indicates that unlimited precision (as many digits as are jaroslav@1258: * required) will be used. Note that leading zeros (in the jaroslav@1258: * coefficient of a number) are never significant. jaroslav@1258: * jaroslav@1258: *

{@code precision} will always be non-negative. jaroslav@1258: * jaroslav@1258: * @serial jaroslav@1258: */ jaroslav@1258: final int precision; jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * The rounding algorithm to be used for an operation. jaroslav@1258: * jaroslav@1258: * @see RoundingMode jaroslav@1258: * @serial jaroslav@1258: */ jaroslav@1258: final RoundingMode roundingMode; jaroslav@1258: jaroslav@1258: /* ----- Constructors ----- */ jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Constructs a new {@code MathContext} with the specified jaroslav@1258: * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding jaroslav@1258: * mode. jaroslav@1258: * jaroslav@1258: * @param setPrecision The non-negative {@code int} precision setting. jaroslav@1258: * @throws IllegalArgumentException if the {@code setPrecision} parameter is less jaroslav@1258: * than zero. jaroslav@1258: */ jaroslav@1258: public MathContext(int setPrecision) { jaroslav@1258: this(setPrecision, DEFAULT_ROUNDINGMODE); jaroslav@1258: return; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Constructs a new {@code MathContext} with a specified jaroslav@1258: * precision and rounding mode. jaroslav@1258: * jaroslav@1258: * @param setPrecision The non-negative {@code int} precision setting. jaroslav@1258: * @param setRoundingMode The rounding mode to use. jaroslav@1258: * @throws IllegalArgumentException if the {@code setPrecision} parameter is less jaroslav@1258: * than zero. jaroslav@1258: * @throws NullPointerException if the rounding mode argument is {@code null} jaroslav@1258: */ jaroslav@1258: public MathContext(int setPrecision, jaroslav@1258: RoundingMode setRoundingMode) { jaroslav@1258: if (setPrecision < MIN_DIGITS) jaroslav@1258: throw new IllegalArgumentException("Digits < 0"); jaroslav@1258: if (setRoundingMode == null) jaroslav@1258: throw new NullPointerException("null RoundingMode"); jaroslav@1258: jaroslav@1258: precision = setPrecision; jaroslav@1258: roundingMode = setRoundingMode; jaroslav@1258: return; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Constructs a new {@code MathContext} from a string. jaroslav@1258: * jaroslav@1258: * The string must be in the same format as that produced by the jaroslav@1258: * {@link #toString} method. jaroslav@1258: * jaroslav@1258: *

An {@code IllegalArgumentException} is thrown if the precision jaroslav@1258: * section of the string is out of range ({@code < 0}) or the string is jaroslav@1258: * not in the format created by the {@link #toString} method. jaroslav@1258: * jaroslav@1258: * @param val The string to be parsed jaroslav@1258: * @throws IllegalArgumentException if the precision section is out of range jaroslav@1258: * or of incorrect format jaroslav@1258: * @throws NullPointerException if the argument is {@code null} jaroslav@1258: */ jaroslav@1258: public MathContext(String val) { jaroslav@1258: boolean bad = false; jaroslav@1258: int setPrecision; jaroslav@1258: if (val == null) jaroslav@1258: throw new NullPointerException("null String"); jaroslav@1258: try { // any error here is a string format problem jaroslav@1258: if (!val.startsWith("precision=")) throw new RuntimeException(); jaroslav@1258: int fence = val.indexOf(' '); // could be -1 jaroslav@1258: int off = 10; // where value starts jaroslav@1258: setPrecision = Integer.parseInt(val.substring(10, fence)); jaroslav@1258: jaroslav@1258: if (!val.startsWith("roundingMode=", fence+1)) jaroslav@1258: throw new RuntimeException(); jaroslav@1258: off = fence + 1 + 13; jaroslav@1258: String str = val.substring(off, val.length()); jaroslav@1258: roundingMode = RoundingMode.valueOf(str); jaroslav@1258: } catch (RuntimeException re) { jaroslav@1258: throw new IllegalArgumentException("bad string format"); jaroslav@1258: } jaroslav@1258: jaroslav@1258: if (setPrecision < MIN_DIGITS) jaroslav@1258: throw new IllegalArgumentException("Digits < 0"); jaroslav@1258: // the other parameters cannot be invalid if we got here jaroslav@1258: precision = setPrecision; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Returns the {@code precision} setting. jaroslav@1258: * This value is always non-negative. jaroslav@1258: * jaroslav@1258: * @return an {@code int} which is the value of the {@code precision} jaroslav@1258: * setting jaroslav@1258: */ jaroslav@1258: public int getPrecision() { jaroslav@1258: return precision; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Returns the roundingMode setting. jaroslav@1258: * This will be one of jaroslav@1258: * {@link RoundingMode#CEILING}, jaroslav@1258: * {@link RoundingMode#DOWN}, jaroslav@1258: * {@link RoundingMode#FLOOR}, jaroslav@1258: * {@link RoundingMode#HALF_DOWN}, jaroslav@1258: * {@link RoundingMode#HALF_EVEN}, jaroslav@1258: * {@link RoundingMode#HALF_UP}, jaroslav@1258: * {@link RoundingMode#UNNECESSARY}, or jaroslav@1258: * {@link RoundingMode#UP}. jaroslav@1258: * jaroslav@1258: * @return a {@code RoundingMode} object which is the value of the jaroslav@1258: * {@code roundingMode} setting jaroslav@1258: */ jaroslav@1258: jaroslav@1258: public RoundingMode getRoundingMode() { jaroslav@1258: return roundingMode; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Compares this {@code MathContext} with the specified jaroslav@1258: * {@code Object} for equality. jaroslav@1258: * jaroslav@1258: * @param x {@code Object} to which this {@code MathContext} is to jaroslav@1258: * be compared. jaroslav@1258: * @return {@code true} if and only if the specified {@code Object} is jaroslav@1258: * a {@code MathContext} object which has exactly the same jaroslav@1258: * settings as this object jaroslav@1258: */ jaroslav@1258: public boolean equals(Object x){ jaroslav@1258: MathContext mc; jaroslav@1258: if (!(x instanceof MathContext)) jaroslav@1258: return false; jaroslav@1258: mc = (MathContext) x; jaroslav@1258: return mc.precision == this.precision jaroslav@1258: && mc.roundingMode == this.roundingMode; // no need for .equals() jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Returns the hash code for this {@code MathContext}. jaroslav@1258: * jaroslav@1258: * @return hash code for this {@code MathContext} jaroslav@1258: */ jaroslav@1258: public int hashCode() { jaroslav@1258: return this.precision + roundingMode.hashCode() * 59; jaroslav@1258: } jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Returns the string representation of this {@code MathContext}. jaroslav@1258: * The {@code String} returned represents the settings of the jaroslav@1258: * {@code MathContext} object as two space-delimited words jaroslav@1258: * (separated by a single space character, '\u0020', jaroslav@1258: * and with no leading or trailing white space), as follows: jaroslav@1258: *

    jaroslav@1258: *
  1. jaroslav@1258: * The string {@code "precision="}, immediately followed jaroslav@1258: * by the value of the precision setting as a numeric string as if jaroslav@1258: * generated by the {@link Integer#toString(int) Integer.toString} jaroslav@1258: * method. jaroslav@1258: * jaroslav@1258: *
  2. jaroslav@1258: * The string {@code "roundingMode="}, immediately jaroslav@1258: * followed by the value of the {@code roundingMode} setting as a jaroslav@1258: * word. This word will be the same as the name of the jaroslav@1258: * corresponding public constant in the {@link RoundingMode} jaroslav@1258: * enum. jaroslav@1258: *
jaroslav@1258: *

jaroslav@1258: * For example: jaroslav@1258: *

jaroslav@1258:      * precision=9 roundingMode=HALF_UP
jaroslav@1258:      * 
jaroslav@1258: * jaroslav@1258: * Additional words may be appended to the result of jaroslav@1258: * {@code toString} in the future if more properties are added to jaroslav@1258: * this class. jaroslav@1258: * jaroslav@1258: * @return a {@code String} representing the context settings jaroslav@1258: */ jaroslav@1258: public java.lang.String toString() { jaroslav@1258: return "precision=" + precision + " " + jaroslav@1258: "roundingMode=" + roundingMode.toString(); jaroslav@1258: } jaroslav@1258: jaroslav@1258: // Private methods jaroslav@1258: jaroslav@1258: /** jaroslav@1258: * Reconstitute the {@code MathContext} instance from a stream (that is, jaroslav@1258: * deserialize it). jaroslav@1258: * jaroslav@1258: * @param s the stream being read. jaroslav@1258: */ jaroslav@1258: private void readObject(java.io.ObjectInputStream s) jaroslav@1258: throws java.io.IOException, ClassNotFoundException { jaroslav@1258: s.defaultReadObject(); // read in all fields jaroslav@1258: // validate possibly bad fields jaroslav@1258: if (precision < MIN_DIGITS) { jaroslav@1258: String message = "MathContext: invalid digits in stream"; jaroslav@1258: throw new java.io.StreamCorruptedException(message); jaroslav@1258: } jaroslav@1258: if (roundingMode == null) { jaroslav@1258: String message = "MathContext: null roundingMode in stream"; jaroslav@1258: throw new java.io.StreamCorruptedException(message); jaroslav@1258: } jaroslav@1258: } jaroslav@1258: jaroslav@1258: }