| /* 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; |
| } |
| } |