mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1558 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1558 lines
		
	
	
		
			48 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<BigDecimal>
 | |
| {
 | |
|   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);
 | |
|   }
 | |
|   
 | |
|   /**
 | |
|    * Returns a BigDecimal whose value is (this / val), with the specified scale
 | |
|    * and rounding according to the RoundingMode 
 | |
|    * @param val the divisor
 | |
|    * @param scale the scale of the BigDecimal returned
 | |
|    * @param roundingMode the rounding mode to use
 | |
|    * @return a BigDecimal whose value is approximately (this / val)
 | |
|    * @throws ArithmeticException if divisor is zero or the rounding mode is
 | |
|    * UNNECESSARY but the specified scale cannot represent the value exactly
 | |
|    * @since 1.5
 | |
|    */
 | |
|   public BigDecimal divide(BigDecimal val, 
 | |
|                            int scale, RoundingMode roundingMode)
 | |
|   {
 | |
|     return divide (val, scale, roundingMode.ordinal());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a BigDecimal whose value is (this / val) rounded according to the
 | |
|    * RoundingMode
 | |
|    * @param val the divisor
 | |
|    * @param roundingMode the rounding mode to use
 | |
|    * @return a BigDecimal whose value is approximately (this / val)
 | |
|    * @throws ArithmeticException if divisor is zero or the rounding mode is
 | |
|    * UNNECESSARY but the specified scale cannot represent the value exactly
 | |
|    */
 | |
|   public BigDecimal divide (BigDecimal val, RoundingMode roundingMode)
 | |
|   {
 | |
|     return divide (val, scale, roundingMode.ordinal());
 | |
|   }
 | |
|   
 | |
|   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 (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, mc.getRoundingMode().ordinal());
 | |
|     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 BigDecimal whose value is the same as this BigDecimal but whose
 | |
|    * representation has a scale of <code>newScale</code>.  If the scale is
 | |
|    * reduced then rounding may occur, according to the RoundingMode.
 | |
|    * @param newScale
 | |
|    * @param roundingMode
 | |
|    * @return a BigDecimal whose scale is as given, whose value is 
 | |
|    * <code>this</code> with possible rounding
 | |
|    * @throws ArithmeticException if the rounding mode is UNNECESSARY but 
 | |
|    * rounding is required 
 | |
|    * @since 1.5
 | |
|    */
 | |
|   public BigDecimal setScale(int newScale, RoundingMode roundingMode)
 | |
|   {
 | |
|     return setScale(newScale, roundingMode.ordinal());
 | |
|   }
 | |
|   
 | |
|   /**
 | |
|    * 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;
 | |
|   }
 | |
| }
 |