| /* java.math.BigDecimal -- Arbitrary precision decimals. | |
| Copyright (C) 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath 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 for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.math; | |
| public class BigDecimal extends Number implements Comparable | |
| { | |
| private BigInteger intVal; | |
| private int scale; | |
| private int precision = 0; | |
| private static final long serialVersionUID = 6108874887143696463L; | |
| /** | |
| * The constant zero as a BigDecimal with scale zero. | |
| * @since 1.5 | |
| */ | |
| public static final BigDecimal ZERO = | |
| new BigDecimal (BigInteger.ZERO, 0); | |
| /** | |
| * The constant one as a BigDecimal with scale zero. | |
| * @since 1.5 | |
| */ | |
| public static final BigDecimal ONE = | |
| new BigDecimal (BigInteger.ONE, 0); | |
| /** | |
| * The constant ten as a BigDecimal with scale zero. | |
| * @since 1.5 | |
| */ | |
| public static final BigDecimal TEN = | |
| new BigDecimal (BigInteger.TEN, 0); | |
| public static final int ROUND_UP = 0; | |
| public static final int ROUND_DOWN = 1; | |
| public static final int ROUND_CEILING = 2; | |
| public static final int ROUND_FLOOR = 3; | |
| public static final int ROUND_HALF_UP = 4; | |
| public static final int ROUND_HALF_DOWN = 5; | |
| public static final int ROUND_HALF_EVEN = 6; | |
| public static final int ROUND_UNNECESSARY = 7; | |
| /** | |
| * Constructs a new BigDecimal whose unscaled value is val and whose | |
| * scale is zero. | |
| * @param val the value of the new BigDecimal | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (int val) | |
| { | |
| this.intVal = BigInteger.valueOf(val); | |
| this.scale = 0; | |
| } | |
| /** | |
| * Constructs a BigDecimal using the BigDecimal(int) constructor and then | |
| * rounds according to the MathContext. | |
| * @param val the value for the initial (unrounded) BigDecimal | |
| * @param mc the MathContext specifying the rounding | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (int val, MathContext mc) | |
| { | |
| this (val); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a new BigDecimal whose unscaled value is val and whose | |
| * scale is zero. | |
| * @param val the value of the new BigDecimal | |
| */ | |
| public BigDecimal (long val) | |
| { | |
| this.intVal = BigInteger.valueOf(val); | |
| this.scale = 0; | |
| } | |
| /** | |
| * Constructs a BigDecimal from the long in the same way as BigDecimal(long) | |
| * and then rounds according to the MathContext. | |
| * @param val the long from which we create the initial BigDecimal | |
| * @param mc the MathContext that specifies the rounding behaviour | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (long val, MathContext mc) | |
| { | |
| this(val); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal whose value is given by num rounded according to | |
| * mc. Since num is already a BigInteger, the rounding refers only to the | |
| * precision setting in mc, if mc.getPrecision() returns an int lower than | |
| * the number of digits in num, then rounding is necessary. | |
| * @param num the unscaledValue, before rounding | |
| * @param mc the MathContext that specifies the precision | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * * @since 1.5 | |
| */ | |
| public BigDecimal (BigInteger num, MathContext mc) | |
| { | |
| this (num, 0); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal from the String val according to the same | |
| * rules as the BigDecimal(String) constructor and then rounds | |
| * according to the MathContext mc. | |
| * @param val the String from which we construct the initial BigDecimal | |
| * @param mc the MathContext that specifies the rounding | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (String val, MathContext mc) | |
| { | |
| this (val); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal whose unscaled value is num and whose | |
| * scale is zero. | |
| * @param num the value of the new BigDecimal | |
| */ | |
| public BigDecimal (BigInteger num) | |
| { | |
| this (num, 0); | |
| } | |
| /** | |
| * Constructs a BigDecimal whose unscaled value is num and whose | |
| * scale is scale. | |
| * @param num | |
| * @param scale | |
| */ | |
| public BigDecimal (BigInteger num, int scale) | |
| { | |
| this.intVal = num; | |
| this.scale = scale; | |
| } | |
| /** | |
| * Constructs a BigDecimal using the BigDecimal(BigInteger, int) | |
| * constructor and then rounds according to the MathContext. | |
| * @param num the unscaled value of the unrounded BigDecimal | |
| * @param scale the scale of the unrounded BigDecimal | |
| * @param mc the MathContext specifying the rounding | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (BigInteger num, int scale, MathContext mc) | |
| { | |
| this (num, scale); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal in the same way as BigDecimal(double) and then | |
| * rounds according to the MathContext. | |
| * @param num the double from which the initial BigDecimal is created | |
| * @param mc the MathContext that specifies the rounding behaviour | |
| * @throws ArithmeticException if the result is inexact but the rounding type | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal (double num, MathContext mc) | |
| { | |
| this (num); | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal result = this.round(mc); | |
| this.intVal = result.intVal; | |
| this.scale = result.scale; | |
| this.precision = result.precision; | |
| } | |
| } | |
| public BigDecimal (double num) throws NumberFormatException | |
| { | |
| if (Double.isInfinite (num) || Double.isNaN (num)) | |
| throw new NumberFormatException ("invalid argument: " + num); | |
| // Note we can't convert NUM to a String and then use the | |
| // String-based constructor. The BigDecimal documentation makes | |
| // it clear that the two constructors work differently. | |
| final int mantissaBits = 52; | |
| final int exponentBits = 11; | |
| final long mantMask = (1L << mantissaBits) - 1; | |
| final long expMask = (1L << exponentBits) - 1; | |
| long bits = Double.doubleToLongBits (num); | |
| long mantissa = bits & mantMask; | |
| long exponent = (bits >>> mantissaBits) & expMask; | |
| boolean denormal = exponent == 0; | |
| // Correct the exponent for the bias. | |
| exponent -= denormal ? 1022 : 1023; | |
| // Now correct the exponent to account for the bits to the right | |
| // of the decimal. | |
| exponent -= mantissaBits; | |
| // Ordinary numbers have an implied leading `1' bit. | |
| if (! denormal) | |
| mantissa |= (1L << mantissaBits); | |
| // Shave off factors of 10. | |
| while (exponent < 0 && (mantissa & 1) == 0) | |
| { | |
| ++exponent; | |
| mantissa >>= 1; | |
| } | |
| intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa); | |
| if (exponent < 0) | |
| { | |
| // We have MANTISSA * 2 ^ (EXPONENT). | |
| // Since (1/2)^N == 5^N * 10^-N we can easily convert this | |
| // into a power of 10. | |
| scale = (int) (- exponent); | |
| BigInteger mult = BigInteger.valueOf (5).pow (scale); | |
| intVal = intVal.multiply (mult); | |
| } | |
| else | |
| { | |
| intVal = intVal.shiftLeft ((int) exponent); | |
| scale = 0; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal from the char subarray and rounding | |
| * according to the MathContext. | |
| * @param in the char array | |
| * @param offset the start of the subarray | |
| * @param len the length of the subarray | |
| * @param mc the MathContext for rounding | |
| * @throws NumberFormatException if the char subarray is not a valid | |
| * BigDecimal representation | |
| * @throws ArithmeticException if the result is inexact but the rounding | |
| * mode is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal(char[] in, int offset, int len, MathContext mc) | |
| { | |
| this(in, offset, len); | |
| // If mc has precision other than zero then we must round. | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal temp = this.round(mc); | |
| this.intVal = temp.intVal; | |
| this.scale = temp.scale; | |
| this.precision = temp.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal from the char array and rounding according | |
| * to the MathContext. | |
| * @param in the char array | |
| * @param mc the MathContext | |
| * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal | |
| * representation | |
| * @throws ArithmeticException if the result is inexact but the rounding mode | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal(char[] in, MathContext mc) | |
| { | |
| this(in, 0, in.length); | |
| // If mc has precision other than zero then we must round. | |
| if (mc.getPrecision() != 0) | |
| { | |
| BigDecimal temp = this.round(mc); | |
| this.intVal = temp.intVal; | |
| this.scale = temp.scale; | |
| this.precision = temp.precision; | |
| } | |
| } | |
| /** | |
| * Constructs a BigDecimal from the given char array, accepting the same | |
| * sequence of characters as the BigDecimal(String) constructor. | |
| * @param in the char array | |
| * @throws NumberFormatException if <code>in</code> is not a valid BigDecimal | |
| * representation | |
| * @since 1.5 | |
| */ | |
| public BigDecimal(char[] in) | |
| { | |
| this(in, 0, in.length); | |
| } | |
| /** | |
| * Constructs a BigDecimal from a char subarray, accepting the same sequence | |
| * of characters as the BigDecimal(String) constructor. | |
| * @param in the char array | |
| * @param offset the start of the subarray | |
| * @param len the length of the subarray | |
| * @throws NumberFormatException if <code>in</code> is not a valid | |
| * BigDecimal representation. | |
| * @since 1.5 | |
| */ | |
| public BigDecimal(char[] in, int offset, int len) | |
| { | |
| // start is the index into the char array where the significand starts | |
| int start = offset; | |
| // end is one greater than the index of the last character used | |
| int end = offset + len; | |
| // point is the index into the char array where the exponent starts | |
| // (or, if there is no exponent, this is equal to end) | |
| int point = offset; | |
| // dot is the index into the char array where the decimal point is | |
| // found, or -1 if there is no decimal point | |
| int dot = -1; | |
| // The following examples show what these variables mean. Note that | |
| // point and dot don't yet have the correct values, they will be | |
| // properly assigned in a loop later on in this method. | |
| // | |
| // Example 1 | |
| // | |
| // + 1 0 2 . 4 6 9 | |
| // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ | |
| // | |
| // offset = 2, len = 8, start = 3, dot = 6, point = end = 10 | |
| // | |
| // Example 2 | |
| // | |
| // + 2 3 4 . 6 1 3 E - 1 | |
| // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ | |
| // | |
| // offset = 2, len = 11, start = 3, dot = 6, point = 10, end = 13 | |
| // | |
| // Example 3 | |
| // | |
| // - 1 2 3 4 5 e 7 | |
| // __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ | |
| // | |
| // offset = 2, len = 8, start = 3, dot = -1, point = 8, end = 10 | |
| // Determine the sign of the number. | |
| boolean negative = false; | |
| if (in[offset] == '+') | |
| { | |
| ++start; | |
| ++point; | |
| } | |
| else if (in[offset] == '-') | |
| { | |
| ++start; | |
| ++point; | |
| negative = true; | |
| } | |
| // Check each character looking for the decimal point and the | |
| // start of the exponent. | |
| while (point < end) | |
| { | |
| char c = in[point]; | |
| if (c == '.') | |
| { | |
| // If dot != -1 then we've seen more than one decimal point. | |
| if (dot != -1) | |
| throw new NumberFormatException("multiple `.'s in number"); | |
| dot = point; | |
| } | |
| // Break when we reach the start of the exponent. | |
| else if (c == 'e' || c == 'E') | |
| break; | |
| // Throw an exception if the character was not a decimal or an | |
| // exponent and is not a digit. | |
| else if (!Character.isDigit(c)) | |
| throw new NumberFormatException("unrecognized character at " + point | |
| + ": " + c); | |
| ++point; | |
| } | |
| // val is a StringBuilder from which we'll create a BigInteger | |
| // which will be the unscaled value for this BigDecimal | |
| StringBuilder val = new StringBuilder(point - start - 1); | |
| if (dot != -1) | |
| { | |
| // If there was a decimal we must combine the two parts that | |
| // contain only digits and we must set the scale properly. | |
| val.append(in, start, dot - start); | |
| val.append(in, dot + 1, point - dot - 1); | |
| scale = point - 1 - dot; | |
| } | |
| else | |
| { | |
| // If there was no decimal then the unscaled value is just the number | |
| // formed from all the digits and the scale is zero. | |
| val.append(in, start, point - start); | |
| scale = 0; | |
| } | |
| if (val.length() == 0) | |
| throw new NumberFormatException("no digits seen"); | |
| // Prepend a negative sign if necessary. | |
| if (negative) | |
| val.insert(0, '-'); | |
| intVal = new BigInteger(val.toString()); | |
| // Now parse exponent. | |
| // If point < end that means we broke out of the previous loop when we | |
| // saw an 'e' or an 'E'. | |
| if (point < end) | |
| { | |
| point++; | |
| // Ignore a '+' sign. | |
| if (in[point] == '+') | |
| point++; | |
| // Throw an exception if there were no digits found after the 'e' | |
| // or 'E'. | |
| if (point >= end) | |
| throw new NumberFormatException("no exponent following e or E"); | |
| try | |
| { | |
| // Adjust the scale according to the exponent. | |
| // Remember that the value of a BigDecimal is | |
| // unscaledValue x Math.pow(10, -scale) | |
| scale -= Integer.parseInt(new String(in, point, end - point)); | |
| } | |
| catch (NumberFormatException ex) | |
| { | |
| throw new NumberFormatException("malformed exponent"); | |
| } | |
| } | |
| } | |
| public BigDecimal (String num) throws NumberFormatException | |
| { | |
| int len = num.length(); | |
| int start = 0, point = 0; | |
| int dot = -1; | |
| boolean negative = false; | |
| if (num.charAt(0) == '+') | |
| { | |
| ++start; | |
| ++point; | |
| } | |
| else if (num.charAt(0) == '-') | |
| { | |
| ++start; | |
| ++point; | |
| negative = true; | |
| } | |
| while (point < len) | |
| { | |
| char c = num.charAt (point); | |
| if (c == '.') | |
| { | |
| if (dot >= 0) | |
| throw new NumberFormatException ("multiple `.'s in number"); | |
| dot = point; | |
| } | |
| else if (c == 'e' || c == 'E') | |
| break; | |
| else if (Character.digit (c, 10) < 0) | |
| throw new NumberFormatException ("unrecognized character: " + c); | |
| ++point; | |
| } | |
| String val; | |
| if (dot >= 0) | |
| { | |
| val = num.substring (start, dot) + num.substring (dot + 1, point); | |
| scale = point - 1 - dot; | |
| } | |
| else | |
| { | |
| val = num.substring (start, point); | |
| scale = 0; | |
| } | |
| if (val.length () == 0) | |
| throw new NumberFormatException ("no digits seen"); | |
| if (negative) | |
| val = "-" + val; | |
| intVal = new BigInteger (val); | |
| // Now parse exponent. | |
| if (point < len) | |
| { | |
| point++; | |
| if (num.charAt(point) == '+') | |
| point++; | |
| if (point >= len ) | |
| throw new NumberFormatException ("no exponent following e or E"); | |
| try | |
| { | |
| scale -= Integer.parseInt (num.substring (point)); | |
| } | |
| catch (NumberFormatException ex) | |
| { | |
| throw new NumberFormatException ("malformed exponent"); | |
| } | |
| } | |
| } | |
| public static BigDecimal valueOf (long val) | |
| { | |
| return valueOf (val, 0); | |
| } | |
| public static BigDecimal valueOf (long val, int scale) | |
| throws NumberFormatException | |
| { | |
| if ((scale == 0) && ((int)val == val)) | |
| switch ((int) val) | |
| { | |
| case 0: | |
| return ZERO; | |
| case 1: | |
| return ONE; | |
| } | |
| return new BigDecimal (BigInteger.valueOf (val), scale); | |
| } | |
| public BigDecimal add (BigDecimal val) | |
| { | |
| // For addition, need to line up decimals. Note that the movePointRight | |
| // method cannot be used for this as it might return a BigDecimal with | |
| // scale == 0 instead of the scale we need. | |
| BigInteger op1 = intVal; | |
| BigInteger op2 = val.intVal; | |
| if (scale < val.scale) | |
| op1 = op1.multiply (BigInteger.TEN.pow (val.scale - scale)); | |
| else if (scale > val.scale) | |
| op2 = op2.multiply (BigInteger.TEN.pow (scale - val.scale)); | |
| return new BigDecimal (op1.add (op2), Math.max (scale, val.scale)); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is found first by calling the | |
| * method add(val) and then by rounding according to the MathContext mc. | |
| * @param val the augend | |
| * @param mc the MathContext for rounding | |
| * @throws ArithmeticException if the value is inexact but the rounding is | |
| * RoundingMode.UNNECESSARY | |
| * @return <code>this</code> + <code>val</code>, rounded if need be | |
| * @since 1.5 | |
| */ | |
| public BigDecimal add (BigDecimal val, MathContext mc) | |
| { | |
| return add(val).round(mc); | |
| } | |
| public BigDecimal subtract (BigDecimal val) | |
| { | |
| return this.add(val.negate()); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is found first by calling the | |
| * method subtract(val) and then by rounding according to the MathContext mc. | |
| * @param val the subtrahend | |
| * @param mc the MathContext for rounding | |
| * @throws ArithmeticException if the value is inexact but the rounding is | |
| * RoundingMode.UNNECESSARY | |
| * @return <code>this</code> - <code>val</code>, rounded if need be | |
| * @since 1.5 | |
| */ | |
| public BigDecimal subtract (BigDecimal val, MathContext mc) | |
| { | |
| return subtract(val).round(mc); | |
| } | |
| public BigDecimal multiply (BigDecimal val) | |
| { | |
| return new BigDecimal (intVal.multiply (val.intVal), scale + val.scale); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is (this x val) before it is rounded | |
| * according to the MathContext mc. | |
| * @param val the multiplicand | |
| * @param mc the MathContext for rounding | |
| * @return a new BigDecimal with value approximately (this x val) | |
| * @throws ArithmeticException if the value is inexact but the rounding mode | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal multiply (BigDecimal val, MathContext mc) | |
| { | |
| return multiply(val).round(mc); | |
| } | |
| public BigDecimal divide (BigDecimal val, int roundingMode) | |
| throws ArithmeticException, IllegalArgumentException | |
| { | |
| return divide (val, scale, roundingMode); | |
| } | |
| public BigDecimal divide(BigDecimal val, int newScale, int roundingMode) | |
| throws ArithmeticException, IllegalArgumentException | |
| { | |
| if (roundingMode < 0 || roundingMode > 7) | |
| throw | |
| new IllegalArgumentException("illegal rounding mode: " + roundingMode); | |
| if (intVal.signum () == 0) // handle special case of 0.0/0.0 | |
| return newScale == 0 ? ZERO : new BigDecimal (ZERO.intVal, newScale); | |
| // Ensure that pow gets a non-negative value. | |
| BigInteger valIntVal = val.intVal; | |
| int power = newScale - (scale - val.scale); | |
| if (power < 0) | |
| { | |
| // Effectively increase the scale of val to avoid an | |
| // ArithmeticException for a negative power. | |
| valIntVal = valIntVal.multiply (BigInteger.TEN.pow (-power)); | |
| power = 0; | |
| } | |
| BigInteger dividend = intVal.multiply (BigInteger.TEN.pow (power)); | |
| BigInteger parts[] = dividend.divideAndRemainder (valIntVal); | |
| BigInteger unrounded = parts[0]; | |
| if (parts[1].signum () == 0) // no remainder, no rounding necessary | |
| return new BigDecimal (unrounded, newScale); | |
| if (roundingMode == ROUND_UNNECESSARY) | |
| throw new ArithmeticException ("Rounding necessary"); | |
| int sign = intVal.signum () * valIntVal.signum (); | |
| if (roundingMode == ROUND_CEILING) | |
| roundingMode = (sign > 0) ? ROUND_UP : ROUND_DOWN; | |
| else if (roundingMode == ROUND_FLOOR) | |
| roundingMode = (sign < 0) ? ROUND_UP : ROUND_DOWN; | |
| else | |
| { | |
| // half is -1 if remainder*2 < positive intValue (*power), 0 if equal, | |
| // 1 if >. This implies that the remainder to round is less than, | |
| // equal to, or greater than half way to the next digit. | |
| BigInteger posRemainder | |
| = parts[1].signum () < 0 ? parts[1].negate() : parts[1]; | |
| valIntVal = valIntVal.signum () < 0 ? valIntVal.negate () : valIntVal; | |
| int half = posRemainder.shiftLeft(1).compareTo(valIntVal); | |
| switch(roundingMode) | |
| { | |
| case ROUND_HALF_UP: | |
| roundingMode = (half < 0) ? ROUND_DOWN : ROUND_UP; | |
| break; | |
| case ROUND_HALF_DOWN: | |
| roundingMode = (half > 0) ? ROUND_UP : ROUND_DOWN; | |
| break; | |
| case ROUND_HALF_EVEN: | |
| if (half < 0) | |
| roundingMode = ROUND_DOWN; | |
| else if (half > 0) | |
| roundingMode = ROUND_UP; | |
| else if (unrounded.testBit(0)) // odd, then ROUND_HALF_UP | |
| roundingMode = ROUND_UP; | |
| else // even, ROUND_HALF_DOWN | |
| roundingMode = ROUND_DOWN; | |
| break; | |
| } | |
| } | |
| if (roundingMode == ROUND_UP) | |
| unrounded = unrounded.add (BigInteger.valueOf (sign > 0 ? 1 : -1)); | |
| // roundingMode == ROUND_DOWN | |
| return new BigDecimal (unrounded, newScale); | |
| } | |
| /** | |
| * Performs division, if the resulting quotient requires rounding | |
| * (has a nonterminating decimal expansion), | |
| * an ArithmeticException is thrown. | |
| * #see divide(BigDecimal, int, int) | |
| * @since 1.5 | |
| */ | |
| public BigDecimal divide(BigDecimal divisor) | |
| throws ArithmeticException, IllegalArgumentException | |
| { | |
| return divide(divisor, scale, ROUND_UNNECESSARY); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is the remainder in the quotient | |
| * this / val. This is obtained by | |
| * subtract(divideToIntegralValue(val).multiply(val)). | |
| * @param val the divisor | |
| * @return a BigDecimal whose value is the remainder | |
| * @throws ArithmeticException if val == 0 | |
| * @since 1.5 | |
| */ | |
| public BigDecimal remainder(BigDecimal val) | |
| { | |
| return subtract(divideToIntegralValue(val).multiply(val)); | |
| } | |
| /** | |
| * Returns a BigDecimal array, the first element of which is the integer part | |
| * of this / val, and the second element of which is the remainder of | |
| * that quotient. | |
| * @param val the divisor | |
| * @return the above described BigDecimal array | |
| * @throws ArithmeticException if val == 0 | |
| * @since 1.5 | |
| */ | |
| public BigDecimal[] divideAndRemainder(BigDecimal val) | |
| { | |
| BigDecimal[] result = new BigDecimal[2]; | |
| result[0] = divideToIntegralValue(val); | |
| result[1] = subtract(result[0].multiply(val)); | |
| return result; | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is the integer part of the quotient | |
| * this / val. The preferred scale is this.scale - val.scale. | |
| * @param val the divisor | |
| * @return a BigDecimal whose value is the integer part of this / val. | |
| * @throws ArithmeticException if val == 0 | |
| * @since 1.5 | |
| */ | |
| public BigDecimal divideToIntegralValue(BigDecimal val) | |
| { | |
| return divide(val, ROUND_DOWN).floor().setScale(scale - val.scale, ROUND_DOWN); | |
| } | |
| /** | |
| * Mutates this BigDecimal into one with no fractional part, whose value is | |
| * equal to the largest integer that is <= to this BigDecimal. Note that | |
| * since this method is private it is okay to mutate this BigDecimal. | |
| * @return the BigDecimal obtained through the floor operation on this | |
| * BigDecimal. | |
| */ | |
| private BigDecimal floor() | |
| { | |
| if (scale <= 0) | |
| return this; | |
| String intValStr = intVal.toString(); | |
| intValStr = intValStr.substring(0, intValStr.length() - scale); | |
| intVal = new BigInteger(intValStr).multiply(BigInteger.TEN.pow(scale)); | |
| return this; | |
| } | |
| public int compareTo (Object obj) | |
| { | |
| return compareTo((BigDecimal) obj); | |
| } | |
| public int compareTo (BigDecimal val) | |
| { | |
| if (scale == val.scale) | |
| return intVal.compareTo (val.intVal); | |
| BigInteger thisParts[] = | |
| intVal.divideAndRemainder (BigInteger.TEN.pow (scale)); | |
| BigInteger valParts[] = | |
| val.intVal.divideAndRemainder (BigInteger.TEN.pow (val.scale)); | |
| int compare; | |
| if ((compare = thisParts[0].compareTo (valParts[0])) != 0) | |
| return compare; | |
| // quotients are the same, so compare remainders | |
| // Add some trailing zeros to the remainder with the smallest scale | |
| if (scale < val.scale) | |
| thisParts[1] = thisParts[1].multiply | |
| (BigInteger.valueOf (10).pow (val.scale - scale)); | |
| else if (scale > val.scale) | |
| valParts[1] = valParts[1].multiply | |
| (BigInteger.valueOf (10).pow (scale - val.scale)); | |
| // and compare them | |
| return thisParts[1].compareTo (valParts[1]); | |
| } | |
| public boolean equals (Object o) | |
| { | |
| return (o instanceof BigDecimal | |
| && scale == ((BigDecimal) o).scale | |
| && compareTo ((BigDecimal) o) == 0); | |
| } | |
| public int hashCode() | |
| { | |
| return intValue() ^ scale; | |
| } | |
| public BigDecimal max (BigDecimal val) | |
| { | |
| switch (compareTo (val)) | |
| { | |
| case 1: | |
| return this; | |
| default: | |
| return val; | |
| } | |
| } | |
| public BigDecimal min (BigDecimal val) | |
| { | |
| switch (compareTo (val)) | |
| { | |
| case -1: | |
| return this; | |
| default: | |
| return val; | |
| } | |
| } | |
| public BigDecimal movePointLeft (int n) | |
| { | |
| return (n < 0) ? movePointRight (-n) : new BigDecimal (intVal, scale + n); | |
| } | |
| public BigDecimal movePointRight (int n) | |
| { | |
| if (n < 0) | |
| return movePointLeft (-n); | |
| if (scale >= n) | |
| return new BigDecimal (intVal, scale - n); | |
| return new BigDecimal (intVal.multiply | |
| (BigInteger.TEN.pow (n - scale)), 0); | |
| } | |
| public int signum () | |
| { | |
| return intVal.signum (); | |
| } | |
| public int scale () | |
| { | |
| return scale; | |
| } | |
| public BigInteger unscaledValue() | |
| { | |
| return intVal; | |
| } | |
| public BigDecimal abs () | |
| { | |
| return new BigDecimal (intVal.abs (), scale); | |
| } | |
| public BigDecimal negate () | |
| { | |
| return new BigDecimal (intVal.negate (), scale); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is found first by negating this via | |
| * the negate() method, then by rounding according to the MathContext mc. | |
| * @param mc the MathContext for rounding | |
| * @return a BigDecimal whose value is approximately (-this) | |
| * @throws ArithmeticException if the value is inexact but the rounding mode | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal negate(MathContext mc) | |
| { | |
| BigDecimal result = negate(); | |
| if (mc.getPrecision() != 0) | |
| result = result.round(mc); | |
| return result; | |
| } | |
| /** | |
| * Returns this BigDecimal. This is included for symmetry with the | |
| * method negate(). | |
| * @return this | |
| * @since 1.5 | |
| */ | |
| public BigDecimal plus() | |
| { | |
| return this; | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is found by rounding <code>this</code> | |
| * according to the MathContext. This is the same as round(MathContext). | |
| * @param mc the MathContext for rounding | |
| * @return a BigDecimal whose value is <code>this</code> before being rounded | |
| * @throws ArithmeticException if the value is inexact but the rounding mode | |
| * is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal plus(MathContext mc) | |
| { | |
| return round(mc); | |
| } | |
| /** | |
| * Returns a BigDecimal which is this BigDecimal rounded according to the | |
| * MathContext rounding settings. | |
| * @param mc the MathContext that tells us how to round | |
| * @return the rounded BigDecimal | |
| */ | |
| public BigDecimal round(MathContext mc) | |
| { | |
| int mcPrecision = mc.getPrecision(); | |
| int numToChop = precision() - mcPrecision; | |
| // If mc specifies not to chop any digits or if we've already chopped | |
| // enough digits (say by using a MathContext in the constructor for this | |
| // BigDecimal) then just return this. | |
| if (mcPrecision == 0 || numToChop <= 0) | |
| return this; | |
| // Make a new BigDecimal which is the correct power of 10 to chop off | |
| // the required number of digits and then call divide. | |
| BigDecimal div = new BigDecimal(BigInteger.TEN.pow(numToChop)); | |
| BigDecimal rounded = divide(div, scale, 4); | |
| rounded.scale -= numToChop; | |
| rounded.precision = mcPrecision; | |
| return rounded; | |
| } | |
| /** | |
| * Returns the precision of this BigDecimal (the number of digits in the | |
| * unscaled value). The precision of a zero value is 1. | |
| * @return the number of digits in the unscaled value, or 1 if the value | |
| * is zero. | |
| */ | |
| public int precision() | |
| { | |
| if (precision == 0) | |
| { | |
| String s = intVal.toString(); | |
| precision = s.length() - (( s.charAt(0) == '-' ) ? 1 : 0); | |
| } | |
| return precision; | |
| } | |
| /** | |
| * Returns the String representation of this BigDecimal, using scientific | |
| * notation if necessary. The following steps are taken to generate | |
| * the result: | |
| * | |
| * 1. the BigInteger unscaledValue's toString method is called and if | |
| * <code>scale == 0<code> is returned. | |
| * 2. an <code>int adjExp</code> is created which is equal to the negation | |
| * of <code>scale</code> plus the number of digits in the unscaled value, | |
| * minus one. | |
| * 3. if <code>scale >= 0 && adjExp >= -6</code> then we represent this | |
| * BigDecimal without scientific notation. A decimal is added if the | |
| * scale is positive and zeros are prepended as necessary. | |
| * 4. if scale is negative or adjExp is less than -6 we use scientific | |
| * notation. If the unscaled value has more than one digit, a decimal | |
| * as inserted after the first digit, the character 'E' is appended | |
| * and adjExp is appended. | |
| */ | |
| public String toString() | |
| { | |
| // bigStr is the String representation of the unscaled value. If | |
| // scale is zero we simply return this. | |
| String bigStr = intVal.toString(); | |
| if (scale == 0) | |
| return bigStr; | |
| boolean negative = (bigStr.charAt(0) == '-'); | |
| int point = bigStr.length() - scale - (negative ? 1 : 0); | |
| StringBuilder val = new StringBuilder(); | |
| if (scale >= 0 && (point - 1) >= -6) | |
| { | |
| // Convert to character form without scientific notation. | |
| if (point <= 0) | |
| { | |
| // Zeros need to be prepended to the StringBuilder. | |
| if (negative) | |
| val.append('-'); | |
| // Prepend a '0' and a '.' and then as many more '0's as necessary. | |
| val.append('0').append('.'); | |
| while (point < 0) | |
| { | |
| val.append('0'); | |
| point++; | |
| } | |
| // Append the unscaled value. | |
| val.append(bigStr.substring(negative ? 1 : 0)); | |
| } | |
| else | |
| { | |
| // No zeros need to be prepended so the String is simply the | |
| // unscaled value with the decimal point inserted. | |
| val.append(bigStr); | |
| val.insert(point + (negative ? 1 : 0), '.'); | |
| } | |
| } | |
| else | |
| { | |
| // We must use scientific notation to represent this BigDecimal. | |
| val.append(bigStr); | |
| // If there is more than one digit in the unscaled value we put a | |
| // decimal after the first digit. | |
| if (bigStr.length() > 1) | |
| val.insert( ( negative ? 2 : 1 ), '.'); | |
| // And then append 'E' and the exponent = (point - 1). | |
| val.append('E'); | |
| if (point - 1 >= 0) | |
| val.append('+'); | |
| val.append( point - 1 ); | |
| } | |
| return val.toString(); | |
| } | |
| /** | |
| * Returns the String representation of this BigDecimal, using engineering | |
| * notation if necessary. This is similar to toString() but when exponents | |
| * are used the exponent is made to be a multiple of 3 such that the integer | |
| * part is between 1 and 999. | |
| * | |
| * @return a String representation of this BigDecimal in engineering notation | |
| * @since 1.5 | |
| */ | |
| public String toEngineeringString() | |
| { | |
| // bigStr is the String representation of the unscaled value. If | |
| // scale is zero we simply return this. | |
| String bigStr = intVal.toString(); | |
| if (scale == 0) | |
| return bigStr; | |
| boolean negative = (bigStr.charAt(0) == '-'); | |
| int point = bigStr.length() - scale - (negative ? 1 : 0); | |
| // This is the adjusted exponent described above. | |
| int adjExp = point - 1; | |
| StringBuilder val = new StringBuilder(); | |
| if (scale >= 0 && adjExp >= -6) | |
| { | |
| // Convert to character form without scientific notation. | |
| if (point <= 0) | |
| { | |
| // Zeros need to be prepended to the StringBuilder. | |
| if (negative) | |
| val.append('-'); | |
| // Prepend a '0' and a '.' and then as many more '0's as necessary. | |
| val.append('0').append('.'); | |
| while (point < 0) | |
| { | |
| val.append('0'); | |
| point++; | |
| } | |
| // Append the unscaled value. | |
| val.append(bigStr.substring(negative ? 1 : 0)); | |
| } | |
| else | |
| { | |
| // No zeros need to be prepended so the String is simply the | |
| // unscaled value with the decimal point inserted. | |
| val.append(bigStr); | |
| val.insert(point + (negative ? 1 : 0), '.'); | |
| } | |
| } | |
| else | |
| { | |
| // We must use scientific notation to represent this BigDecimal. | |
| // The exponent must be a multiple of 3 and the integer part | |
| // must be between 1 and 999. | |
| val.append(bigStr); | |
| int zeros = adjExp % 3; | |
| int dot = 1; | |
| if (adjExp > 0) | |
| { | |
| // If the exponent is positive we just move the decimal to the | |
| // right and decrease the exponent until it is a multiple of 3. | |
| dot += zeros; | |
| adjExp -= zeros; | |
| } | |
| else | |
| { | |
| // If the exponent is negative then we move the dot to the right | |
| // and decrease the exponent (increase its magnitude) until | |
| // it is a multiple of 3. Note that this is not adjExp -= zeros | |
| // because the mod operator doesn't give us the distance to the | |
| // correct multiple of 3. (-5 mod 3) is -2 but the distance from | |
| // -5 to the correct multiple of 3 (-6) is 1, not 2. | |
| if (zeros == -2) | |
| { | |
| dot += 1; | |
| adjExp -= 1; | |
| } | |
| else if (zeros == -1) | |
| { | |
| dot += 2; | |
| adjExp -= 2; | |
| } | |
| } | |
| // Either we have to append zeros because, for example, 1.1E+5 should | |
| // be 110E+3, or we just have to put the decimal in the right place. | |
| if (dot > val.length()) | |
| { | |
| while (dot > val.length()) | |
| val.append('0'); | |
| } | |
| else if (bigStr.length() > dot) | |
| val.insert(dot + (negative ? 1 : 0), '.'); | |
| // And then append 'E' and the exponent (adjExp). | |
| val.append('E'); | |
| if (adjExp >= 0) | |
| val.append('+'); | |
| val.append(adjExp); | |
| } | |
| return val.toString(); | |
| } | |
| /** | |
| * Returns a String representation of this BigDecimal without using | |
| * scientific notation. This is how toString() worked for releases 1.4 | |
| * and previous. Zeros may be added to the end of the String. For | |
| * example, an unscaled value of 1234 and a scale of -3 would result in | |
| * the String 1234000, but the toString() method would return | |
| * 1.234E+6. | |
| * @return a String representation of this BigDecimal | |
| * @since 1.5 | |
| */ | |
| public String toPlainString() | |
| { | |
| // If the scale is zero we simply return the String representation of the | |
| // unscaled value. | |
| String bigStr = intVal.toString(); | |
| if (scale == 0) | |
| return bigStr; | |
| // Remember if we have to put a negative sign at the start. | |
| boolean negative = (bigStr.charAt(0) == '-'); | |
| int point = bigStr.length() - scale - (negative ? 1 : 0); | |
| StringBuffer sb = new StringBuffer(bigStr.length() + 2 | |
| + (point <= 0 ? (-point + 1) : 0)); | |
| if (point <= 0) | |
| { | |
| // We have to prepend zeros and a decimal point. | |
| if (negative) | |
| sb.append('-'); | |
| sb.append('0').append('.'); | |
| while (point < 0) | |
| { | |
| sb.append('0'); | |
| point++; | |
| } | |
| sb.append(bigStr.substring(negative ? 1 : 0)); | |
| } | |
| else if (point < bigStr.length()) | |
| { | |
| // No zeros need to be prepended or appended, just put the decimal | |
| // in the right place. | |
| sb.append(bigStr); | |
| sb.insert(point + (negative ? 1 : 0), '.'); | |
| } | |
| else | |
| { | |
| // We must append zeros instead of using scientific notation. | |
| sb.append(bigStr); | |
| for (int i = bigStr.length(); i < point; i++) | |
| sb.append('0'); | |
| } | |
| return sb.toString(); | |
| } | |
| /** | |
| * Converts this BigDecimal to a BigInteger. Any fractional part will | |
| * be discarded. | |
| * @return a BigDecimal whose value is equal to floor[this] | |
| */ | |
| public BigInteger toBigInteger () | |
| { | |
| // If scale > 0 then we must divide, if scale > 0 then we must multiply, | |
| // and if scale is zero then we just return intVal; | |
| if (scale > 0) | |
| return intVal.divide (BigInteger.TEN.pow (scale)); | |
| else if (scale < 0) | |
| return intVal.multiply(BigInteger.TEN.pow(-scale)); | |
| return intVal; | |
| } | |
| /** | |
| * Converts this BigDecimal into a BigInteger, throwing an | |
| * ArithmeticException if the conversion is not exact. | |
| * @return a BigInteger whose value is equal to the value of this BigDecimal | |
| * @since 1.5 | |
| */ | |
| public BigInteger toBigIntegerExact() | |
| { | |
| if (scale > 0) | |
| { | |
| // If we have to divide, we must check if the result is exact. | |
| BigInteger[] result = | |
| intVal.divideAndRemainder(BigInteger.TEN.pow(scale)); | |
| if (result[1].equals(BigInteger.ZERO)) | |
| return result[0]; | |
| throw new ArithmeticException("No exact BigInteger representation"); | |
| } | |
| else if (scale < 0) | |
| // If we're multiplying instead, then we needn't check for exactness. | |
| return intVal.multiply(BigInteger.TEN.pow(-scale)); | |
| // If the scale is zero we can simply return intVal. | |
| return intVal; | |
| } | |
| public int intValue () | |
| { | |
| return toBigInteger ().intValue (); | |
| } | |
| /** | |
| * Returns a BigDecimal which is numerically equal to this BigDecimal but | |
| * with no trailing zeros in the representation. For example, if this | |
| * BigDecimal has [unscaledValue, scale] = [6313000, 4] this method returns | |
| * a BigDecimal with [unscaledValue, scale] = [6313, 1]. As another | |
| * example, [12400, -2] would become [124, -4]. | |
| * @return a numerically equal BigDecimal with no trailing zeros | |
| */ | |
| public BigDecimal stripTrailingZeros() | |
| { | |
| String intValStr = intVal.toString(); | |
| int newScale = scale; | |
| int pointer = intValStr.length() - 1; | |
| // This loop adjusts pointer which will be used to give us the substring | |
| // of intValStr to use in our new BigDecimal, and also accordingly | |
| // adjusts the scale of our new BigDecimal. | |
| while (intValStr.charAt(pointer) == '0') | |
| { | |
| pointer --; | |
| newScale --; | |
| } | |
| // Create a new BigDecimal with the appropriate substring and then | |
| // set its scale. | |
| BigDecimal result = new BigDecimal(intValStr.substring(0, pointer + 1)); | |
| result.scale = newScale; | |
| return result; | |
| } | |
| public long longValue () | |
| { | |
| return toBigInteger().longValue(); | |
| } | |
| public float floatValue() | |
| { | |
| return Float.valueOf(toString()).floatValue(); | |
| } | |
| public double doubleValue() | |
| { | |
| return Double.valueOf(toString()).doubleValue(); | |
| } | |
| public BigDecimal setScale (int scale) throws ArithmeticException | |
| { | |
| return setScale (scale, ROUND_UNNECESSARY); | |
| } | |
| public BigDecimal setScale (int scale, int roundingMode) | |
| throws ArithmeticException, IllegalArgumentException | |
| { | |
| // NOTE: The 1.5 JRE doesn't throw this, ones prior to it do and | |
| // the spec says it should. Nevertheless, if 1.6 doesn't fix this | |
| // we should consider removing it. | |
| if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0."); | |
| return divide (ONE, scale, roundingMode); | |
| } | |
| /** | |
| * Returns a new BigDecimal constructed from the BigDecimal(String) | |
| * constructor using the Double.toString(double) method to obtain | |
| * the String. | |
| * @param val the double value used in Double.toString(double) | |
| * @return a BigDecimal representation of val | |
| * @throws NumberFormatException if val is NaN or infinite | |
| * @since 1.5 | |
| */ | |
| public static BigDecimal valueOf(double val) | |
| { | |
| if (Double.isInfinite(val) || Double.isNaN(val)) | |
| throw new NumberFormatException("argument cannot be NaN or infinite."); | |
| return new BigDecimal(Double.toString(val)); | |
| } | |
| /** | |
| * Returns a BigDecimal whose numerical value is the numerical value | |
| * of this BigDecimal multiplied by 10 to the power of <code>n</code>. | |
| * @param n the power of ten | |
| * @return the new BigDecimal | |
| * @since 1.5 | |
| */ | |
| public BigDecimal scaleByPowerOfTen(int n) | |
| { | |
| BigDecimal result = new BigDecimal(intVal, scale - n); | |
| result.precision = precision; | |
| return result; | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is <code>this</code> to the power of | |
| * <code>n</code>. | |
| * @param n the power | |
| * @return the new BigDecimal | |
| * @since 1.5 | |
| */ | |
| public BigDecimal pow(int n) | |
| { | |
| if (n < 0 || n > 999999999) | |
| throw new ArithmeticException("n must be between 0 and 999999999"); | |
| BigDecimal result = new BigDecimal(intVal.pow(n), scale * n); | |
| return result; | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is determined by first calling pow(n) | |
| * and then by rounding according to the MathContext mc. | |
| * @param n the power | |
| * @param mc the MathContext | |
| * @return the new BigDecimal | |
| * @throws ArithmeticException if n < 0 or n > 999999999 or if the result is | |
| * inexact but the rounding is RoundingMode.UNNECESSARY | |
| * @since 1.5 | |
| */ | |
| public BigDecimal pow(int n, MathContext mc) | |
| { | |
| // FIXME: The specs claim to use the X3.274-1996 algorithm. We | |
| // currently do not. | |
| return pow(n).round(mc); | |
| } | |
| /** | |
| * Returns a BigDecimal whose value is the absolute value of this BigDecimal | |
| * with rounding according to the given MathContext. | |
| * @param mc the MathContext | |
| * @return the new BigDecimal | |
| */ | |
| public BigDecimal abs(MathContext mc) | |
| { | |
| BigDecimal result = abs(); | |
| result = result.round(mc); | |
| return result; | |
| } | |
| /** | |
| * Returns the size of a unit in the last place of this BigDecimal. This | |
| * returns a BigDecimal with [unscaledValue, scale] = [1, this.scale()]. | |
| * @return the size of a unit in the last place of <code>this</code>. | |
| * @since 1.5 | |
| */ | |
| public BigDecimal ulp() | |
| { | |
| return new BigDecimal(BigInteger.ONE, scale); | |
| } | |
| /** | |
| * Converts this BigDecimal to a long value. | |
| * @return the long value | |
| * @throws ArithmeticException if rounding occurs or if overflow occurs | |
| * @since 1.5 | |
| */ | |
| public long longValueExact() | |
| { | |
| // Set scale will throw an exception if rounding occurs. | |
| BigDecimal temp = setScale(0, ROUND_UNNECESSARY); | |
| BigInteger tempVal = temp.intVal; | |
| // Check for overflow. | |
| long result = intVal.longValue(); | |
| if (tempVal.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 1 | |
| || (result < 0 && signum() == 1) || (result > 0 && signum() == -1)) | |
| throw new ArithmeticException("this BigDecimal is too " + | |
| "large to fit into the return type"); | |
| return intVal.longValue(); | |
| } | |
| /** | |
| * Converts this BigDecimal into an int by first calling longValueExact | |
| * and then checking that the <code>long</code> returned from that | |
| * method fits into an <code>int</code>. | |
| * @return an int whose value is <code>this</code> | |
| * @throws ArithmeticException if this BigDecimal has a fractional part | |
| * or is too large to fit into an int. | |
| * @since 1.5 | |
| */ | |
| public int intValueExact() | |
| { | |
| long temp = longValueExact(); | |
| int result = (int)temp; | |
| if (result != temp) | |
| throw new ArithmeticException ("this BigDecimal cannot fit into an int"); | |
| return result; | |
| } | |
| /** | |
| * Converts this BigDecimal into a byte by first calling longValueExact | |
| * and then checking that the <code>long</code> returned from that | |
| * method fits into a <code>byte</code>. | |
| * @return a byte whose value is <code>this</code> | |
| * @throws ArithmeticException if this BigDecimal has a fractional part | |
| * or is too large to fit into a byte. | |
| * @since 1.5 | |
| */ | |
| public byte byteValueExact() | |
| { | |
| long temp = longValueExact(); | |
| byte result = (byte)temp; | |
| if (result != temp) | |
| throw new ArithmeticException ("this BigDecimal cannot fit into a byte"); | |
| return result; | |
| } | |
| /** | |
| * Converts this BigDecimal into a short by first calling longValueExact | |
| * and then checking that the <code>long</code> returned from that | |
| * method fits into a <code>short</code>. | |
| * @return a short whose value is <code>this</code> | |
| * @throws ArithmeticException if this BigDecimal has a fractional part | |
| * or is too large to fit into a short. | |
| * @since 1.5 | |
| */ | |
| public short shortValueExact() | |
| { | |
| long temp = longValueExact(); | |
| short result = (short)temp; | |
| if (result != temp) | |
| throw new ArithmeticException ("this BigDecimal cannot fit into a short"); | |
| return result; | |
| } | |
| } |