/* |
|
* Copyright (c) 2003, 2007, 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 |
|
* @author Mike Cowlishaw |
|
* @author Joseph D. Darcy |
|
* @since 1.5 |
|
*/ |
|
public final class MathContext implements Serializable { |
|
/* ----- Constants ----- */ |
|
// defaults for constructors |
|
private static final int DEFAULT_DIGITS = 9; |
|
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 |
|
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 |
|
* </code> |
|
*/ |
|
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. |
|
*/ |
|
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. |
|
*/ |
|
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. |
|
*/ |
|
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); |
|
return; |
|
} |
|
/** |
|
* 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; |
|
return; |
|
} |
|
/** |
|
* 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) { |
|
boolean bad = false; |
|
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){ |
|
MathContext mc; |
|
if (!(x instanceof MathContext)) |
|
return false; |
|
mc = (MathContext) x; |
|
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, <tt>'\u0020'</tt>, |
|
* 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. |
|
*/ |
|
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); |
|
} |
|
} |
|
} |