mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1515 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1515 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Java
		
	
	
	
/* 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;
 | 
						|
  }
 | 
						|
}
 |