2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.io.Serializable;
23 import java.io.StreamCorruptedException;
26 * Immutable objects describing settings such as rounding mode and digit
27 * precision for the numerical operations provided by class {@link BigDecimal}.
29 public final class MathContext implements Serializable {
32 * A {@code MathContext} which corresponds to the IEEE 754r quadruple
33 * decimal precision format: 34 digit precision and
34 * {@link RoundingMode#HALF_EVEN} rounding.
36 public static final MathContext DECIMAL128 = new MathContext(34,
37 RoundingMode.HALF_EVEN);
40 * A {@code MathContext} which corresponds to the IEEE 754r single decimal
41 * precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN}
44 public static final MathContext DECIMAL32 = new MathContext(7,
45 RoundingMode.HALF_EVEN);
48 * A {@code MathContext} which corresponds to the IEEE 754r double decimal
49 * precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN}
52 public static final MathContext DECIMAL64 = new MathContext(16,
53 RoundingMode.HALF_EVEN);
56 * A {@code MathContext} for unlimited precision with
57 * {@link RoundingMode#HALF_UP} rounding.
59 public static final MathContext UNLIMITED = new MathContext(0,
60 RoundingMode.HALF_UP);
62 /** This is the serialVersionUID used by the sun implementation */
63 private static final long serialVersionUID = 5579720004786848255L;
66 * The number of digits to be used for an operation; results are rounded to
69 private int precision;
72 * A {@code RoundingMode} object which specifies the algorithm to be used
75 private RoundingMode roundingMode;
78 * An array of {@code char} containing: {@code
79 * 'p','r','e','c','i','s','i','o','n','='}. It's used to improve the
80 * methods related to {@code String} conversion.
82 * @see #MathContext(String)
85 private final static char[] chPrecision = { 'p', 'r', 'e', 'c', 'i', 's',
89 * An array of {@code char} containing: {@code
90 * 'r','o','u','n','d','i','n','g','M','o','d','e','='}. It's used to
91 * improve the methods related to {@code String} conversion.
93 * @see #MathContext(String)
96 private final static char[] chRoundingMode = { 'r', 'o', 'u', 'n', 'd',
97 'i', 'n', 'g', 'M', 'o', 'd', 'e', '=' };
100 * Constructs a new {@code MathContext} with the specified precision and
101 * with the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the
102 * precision passed is zero, then this implies that the computations have to
103 * be performed exact, the rounding mode in this case is irrelevant.
106 * the precision for the new {@code MathContext}.
107 * @throws IllegalArgumentException
108 * if {@code precision < 0}.
110 public MathContext(int precision) {
111 this(precision, RoundingMode.HALF_UP);
115 * Constructs a new {@code MathContext} with the specified precision and
116 * with the specified rounding mode. If the precision passed is zero, then
117 * this implies that the computations have to be performed exact, the
118 * rounding mode in this case is irrelevant.
121 * the precision for the new {@code MathContext}.
122 * @param roundingMode
123 * the rounding mode for the new {@code MathContext}.
124 * @throws IllegalArgumentException
125 * if {@code precision < 0}.
126 * @throws NullPointerException
127 * if {@code roundingMode} is {@code null}.
129 public MathContext(int precision, RoundingMode roundingMode) {
131 throw new IllegalArgumentException("precision < 0");
133 if (roundingMode == null) {
134 throw new NullPointerException("roundingMode == null");
136 this.precision = precision;
137 this.roundingMode = roundingMode;
141 * Constructs a new {@code MathContext} from a string. The string has to
142 * specify the precision and the rounding mode to be used and has to follow
143 * the following syntax: "precision=<precision> roundingMode=<roundingMode>"
144 * This is the same form as the one returned by the {@link #toString}
148 * a string describing the precision and rounding mode for the
149 * new {@code MathContext}.
150 * @throws IllegalArgumentException
151 * if the string is not in the correct format or if the
152 * precision specified is < 0.
154 public MathContext(String val) {
155 char[] charVal = val.toCharArray();
156 int i; // Index of charVal
157 int j; // Index of chRoundingMode
158 int digit; // It will contain the digit parsed
160 if ((charVal.length < 27) || (charVal.length > 45)) {
161 throw new IllegalArgumentException("Bad string format");
163 // Parsing "precision=" String
164 for (i = 0; (i < chPrecision.length) && (charVal[i] == chPrecision[i]); i++) {
168 if (i < chPrecision.length) {
169 throw new IllegalArgumentException("Bad string format");
171 // Parsing the value for "precision="...
172 digit = Character.digit(charVal[i], 10);
174 throw new IllegalArgumentException("Bad string format");
176 // BEGIN android-changed
177 this.precision = digit;
178 // END android-changed
182 digit = Character.digit(charVal[i], 10);
184 if (charVal[i] == ' ') {
185 // It parsed all the digits
189 // It isn't a valid digit, and isn't a white space
190 throw new IllegalArgumentException("Bad string format");
192 // Accumulating the value parsed
193 this.precision = this.precision * 10 + digit;
194 if (this.precision < 0) {
195 throw new IllegalArgumentException("Bad string format");
199 // Parsing "roundingMode="
200 for (j = 0; (j < chRoundingMode.length)
201 && (charVal[i] == chRoundingMode[j]); i++, j++) {
205 if (j < chRoundingMode.length) {
206 throw new IllegalArgumentException("Bad string format");
208 // Parsing the value for "roundingMode"...
209 this.roundingMode = RoundingMode.valueOf(String.valueOf(charVal, i,
210 charVal.length - i));
216 * Returns the precision. The precision is the number of digits used for an
217 * operation. Results are rounded to this precision. The precision is
218 * guaranteed to be non negative. If the precision is zero, then the
219 * computations have to be performed exact, results are not rounded in this
222 * @return the precision.
224 public int getPrecision() {
229 * Returns the rounding mode. The rounding mode is the strategy to be used
232 * The rounding mode is one of
233 * {@link RoundingMode#UP},
234 * {@link RoundingMode#DOWN},
235 * {@link RoundingMode#CEILING},
236 * {@link RoundingMode#FLOOR},
237 * {@link RoundingMode#HALF_UP},
238 * {@link RoundingMode#HALF_DOWN},
239 * {@link RoundingMode#HALF_EVEN}, or
240 * {@link RoundingMode#UNNECESSARY}.
242 * @return the rounding mode.
244 public RoundingMode getRoundingMode() {
249 * Returns true if x is a {@code MathContext} with the same precision
250 * setting and the same rounding mode as this {@code MathContext} instance.
253 * object to be compared.
254 * @return {@code true} if this {@code MathContext} instance is equal to the
255 * {@code x} argument; {@code false} otherwise.
258 public boolean equals(Object x) {
259 return ((x instanceof MathContext)
260 && (((MathContext) x).getPrecision() == precision) && (((MathContext) x)
261 .getRoundingMode() == roundingMode));
265 * Returns the hash code for this {@code MathContext} instance.
267 * @return the hash code for this {@code MathContext}.
270 public int hashCode() {
271 // Make place for the necessary bits to represent 8 rounding modes
272 return ((precision << 3) | roundingMode.ordinal());
276 * Returns the string representation for this {@code MathContext} instance.
277 * The string has the form
279 * "precision=<precision> roundingMode=<roundingMode>"
280 * } where {@code <precision>} is an integer describing the number
281 * of digits used for operations and {@code <roundingMode>} is the
282 * string representation of the rounding mode.
284 * @return a string representation for this {@code MathContext} instance
287 public String toString() {
288 return "precision=" + precision + " roundingMode=" + roundingMode;
292 * Makes checks upon deserialization of a {@code MathContext} instance.
293 * Checks whether {@code precision >= 0} and {@code roundingMode != null}
295 * @throws StreamCorruptedException
296 * if {@code precision < 0}
297 * @throws StreamCorruptedException
298 * if {@code roundingMode == null}
300 private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
301 s.defaultReadObject();
303 throw new StreamCorruptedException("precision < 0");
305 if (roundingMode == null) {
306 throw new StreamCorruptedException("roundingMode == null");