1 /* 2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved. 28 */ 29 30 package java.math; 31 import java.io.*; 32 33 /** 34 * Immutable objects which encapsulate the context settings which 35 * describe certain rules for numerical operators, such as those 36 * implemented by the {@link BigDecimal} class. 37 * 38 * <p>The base-independent settings are: 39 * <ol> 40 * <li>{@code precision}: 41 * the number of digits to be used for an operation; results are 42 * rounded to this precision 43 * 44 * <li>{@code roundingMode}: 45 * a {@link RoundingMode} object which specifies the algorithm to be 46 * used for rounding. 47 * </ol> 48 * 49 * @see BigDecimal 50 * @see RoundingMode 51 * @author Mike Cowlishaw 52 * @author Joseph D. Darcy 53 * @since 1.5 54 */ 55 56 public final class MathContext implements Serializable { 57 58 /* ----- Constants ----- */ 59 60 // defaults for constructors 61 private static final int DEFAULT_DIGITS = 9; 62 private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP; 63 // Smallest values for digits (Maximum is Integer.MAX_VALUE) 64 private static final int MIN_DIGITS = 0; 65 66 // Serialization version 67 private static final long serialVersionUID = 5579720004786848255L; 68 69 /* ----- Public Properties ----- */ 70 /** 71 * A {@code MathContext} object whose settings have the values 72 * required for unlimited precision arithmetic. 73 * The values of the settings are: 74 * <code> 75 * precision=0 roundingMode=HALF_UP 76 * </code> 77 */ 78 public static final MathContext UNLIMITED = 79 new MathContext(0, RoundingMode.HALF_UP); 80 81 /** 82 * A {@code MathContext} object with a precision setting 83 * matching the IEEE 754R Decimal32 format, 7 digits, and a 84 * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the 85 * IEEE 754R default. 86 */ 87 public static final MathContext DECIMAL32 = 88 new MathContext(7, RoundingMode.HALF_EVEN); 89 90 /** 91 * A {@code MathContext} object with a precision setting 92 * matching the IEEE 754R Decimal64 format, 16 digits, and a 93 * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the 94 * IEEE 754R default. 95 */ 96 public static final MathContext DECIMAL64 = 97 new MathContext(16, RoundingMode.HALF_EVEN); 98 99 /** 100 * A {@code MathContext} object with a precision setting 101 * matching the IEEE 754R Decimal128 format, 34 digits, and a 102 * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the 103 * IEEE 754R default. 104 */ 105 public static final MathContext DECIMAL128 = 106 new MathContext(34, RoundingMode.HALF_EVEN); 107 108 /* ----- Shared Properties ----- */ 109 /** 110 * The number of digits to be used for an operation. A value of 0 111 * indicates that unlimited precision (as many digits as are 112 * required) will be used. Note that leading zeros (in the 113 * coefficient of a number) are never significant. 114 * 115 * <p>{@code precision} will always be non-negative. 116 * 117 * @serial 118 */ 119 final int precision; 120 121 /** 122 * The rounding algorithm to be used for an operation. 123 * 124 * @see RoundingMode 125 * @serial 126 */ 127 final RoundingMode roundingMode; 128 129 /* ----- Constructors ----- */ 130 131 /** 132 * Constructs a new {@code MathContext} with the specified 133 * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding 134 * mode. 135 * 136 * @param setPrecision The non-negative {@code int} precision setting. 137 * @throws IllegalArgumentException if the {@code setPrecision} parameter is less 138 * than zero. 139 */ MathContext(int setPrecision)140 public MathContext(int setPrecision) { 141 this(setPrecision, DEFAULT_ROUNDINGMODE); 142 return; 143 } 144 145 /** 146 * Constructs a new {@code MathContext} with a specified 147 * 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 less 152 * than zero. 153 * @throws NullPointerException if the rounding mode argument is {@code null} 154 */ MathContext(int setPrecision, RoundingMode setRoundingMode)155 public MathContext(int setPrecision, 156 RoundingMode setRoundingMode) { 157 if (setPrecision < MIN_DIGITS) 158 throw new IllegalArgumentException("Digits < 0"); 159 if (setRoundingMode == null) 160 throw new NullPointerException("null RoundingMode"); 161 162 precision = setPrecision; 163 roundingMode = setRoundingMode; 164 return; 165 } 166 167 /** 168 * Constructs a new {@code MathContext} from a string. 169 * 170 * The string must be in the same format as that produced by the 171 * {@link #toString} method. 172 * 173 * <p>An {@code IllegalArgumentException} is thrown if the precision 174 * section of the string is out of range ({@code < 0}) or the string is 175 * not in the format created by the {@link #toString} method. 176 * 177 * @param val The string to be parsed 178 * @throws IllegalArgumentException if the precision section is out of range 179 * or of incorrect format 180 * @throws NullPointerException if the argument is {@code null} 181 */ MathContext(String val)182 public MathContext(String val) { 183 boolean bad = false; 184 int setPrecision; 185 if (val == null) 186 throw new NullPointerException("null String"); 187 try { // any error here is a string format problem 188 if (!val.startsWith("precision=")) throw new RuntimeException(); 189 int fence = val.indexOf(' '); // could be -1 190 int off = 10; // where value starts 191 setPrecision = Integer.parseInt(val.substring(10, fence)); 192 193 if (!val.startsWith("roundingMode=", fence+1)) 194 throw new RuntimeException(); 195 off = fence + 1 + 13; 196 String str = val.substring(off, val.length()); 197 roundingMode = RoundingMode.valueOf(str); 198 } catch (RuntimeException re) { 199 throw new IllegalArgumentException("bad string format"); 200 } 201 202 if (setPrecision < MIN_DIGITS) 203 throw new IllegalArgumentException("Digits < 0"); 204 // the other parameters cannot be invalid if we got here 205 precision = setPrecision; 206 } 207 208 /** 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 * setting 214 */ getPrecision()215 public int getPrecision() { 216 return precision; 217 } 218 219 /** 220 * Returns the roundingMode setting. 221 * This will be one of 222 * {@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}, or 229 * {@link RoundingMode#UP}. 230 * 231 * @return a {@code RoundingMode} object which is the value of the 232 * {@code roundingMode} setting 233 */ 234 getRoundingMode()235 public RoundingMode getRoundingMode() { 236 return roundingMode; 237 } 238 239 /** 240 * Compares this {@code MathContext} with the specified 241 * {@code Object} for equality. 242 * 243 * @param x {@code Object} to which this {@code MathContext} is to 244 * be compared. 245 * @return {@code true} if and only if the specified {@code Object} is 246 * a {@code MathContext} object which has exactly the same 247 * settings as this object 248 */ equals(Object x)249 public boolean equals(Object x){ 250 MathContext mc; 251 if (!(x instanceof MathContext)) 252 return false; 253 mc = (MathContext) x; 254 return mc.precision == this.precision 255 && mc.roundingMode == this.roundingMode; // no need for .equals() 256 } 257 258 /** 259 * Returns the hash code for this {@code MathContext}. 260 * 261 * @return hash code for this {@code MathContext} 262 */ hashCode()263 public int hashCode() { 264 return this.precision + roundingMode.hashCode() * 59; 265 } 266 267 /** 268 * Returns the string representation of this {@code MathContext}. 269 * The {@code String} returned represents the settings of the 270 * {@code MathContext} object as two space-delimited words 271 * (separated by a single space character, <code>'\u0020'</code>, 272 * and with no leading or trailing white space), as follows: 273 * <ol> 274 * <li> 275 * The string {@code "precision="}, immediately followed 276 * by the value of the precision setting as a numeric string as if 277 * generated by the {@link Integer#toString(int) Integer.toString} 278 * method. 279 * 280 * <li> 281 * The string {@code "roundingMode="}, immediately 282 * followed by the value of the {@code roundingMode} setting as a 283 * word. This word will be the same as the name of the 284 * corresponding public constant in the {@link RoundingMode} 285 * enum. 286 * </ol> 287 * <p> 288 * For example: 289 * <pre> 290 * precision=9 roundingMode=HALF_UP 291 * </pre> 292 * 293 * Additional words may be appended to the result of 294 * {@code toString} in the future if more properties are added to 295 * this class. 296 * 297 * @return a {@code String} representing the context settings 298 */ toString()299 public java.lang.String toString() { 300 return "precision=" + precision + " " + 301 "roundingMode=" + roundingMode.toString(); 302 } 303 304 // Private methods 305 306 /** 307 * Reconstitute the {@code MathContext} instance from a stream (that is, 308 * deserialize it). 309 * 310 * @param s the stream being read. 311 */ readObject(java.io.ObjectInputStream s)312 private void readObject(java.io.ObjectInputStream s) 313 throws java.io.IOException, ClassNotFoundException { 314 s.defaultReadObject(); // read in all fields 315 // validate possibly bad fields 316 if (precision < MIN_DIGITS) { 317 String message = "MathContext: invalid digits in stream"; 318 throw new java.io.StreamCorruptedException(message); 319 } 320 if (roundingMode == null) { 321 String message = "MathContext: null roundingMode in stream"; 322 throw new java.io.StreamCorruptedException(message); 323 } 324 } 325 326 } 327