src/java.base/share/classes/java/math/MathContext.java
changeset 47216 71c04702a3d5
parent 32033 bf24e33c7919
child 57956 e0b8b019d2f5
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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      */
       
   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      */
       
   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      */
       
   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      */
       
   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 
       
   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      */
       
   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      */
       
   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>'&#92;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      */
       
   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      */
       
   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 }