home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / math / BigDecimal.java next >
Encoding:
Java Source  |  1999-05-28  |  33.4 KB  |  891 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)BigDecimal.java    1.18 98/10/27
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.math;
  16.  
  17. /**
  18.  * Immutable, arbitrary-precision signed decimal numbers.  A BigDecimal
  19.  * consists of an arbitrary precision integer <i>unscaled value</i> and a
  20.  * non-negative 32-bit integer <i>scale</i>, which represents the number of
  21.  * digits to the right of the decimal point.  The number represented by the
  22.  * BigDecimal is <tt>(unscaledValue/10<sup>scale</sup>)</tt>.  BigDecimal
  23.  * provides operations for basic arithmetic, scale manipulation, comparison,
  24.  * hashing, and format conversion.
  25.  * <p>
  26.  * The BigDecimal class gives its user complete control over rounding
  27.  * behavior, forcing the user to explicitly specify a rounding behavior for
  28.  * operations capable of discarding precision (<tt>divide</tt> and
  29.  * <tt>setScale</tt>).  Eight <em>rounding modes</em> are provided for this
  30.  * purpose.
  31.  * <p>
  32.  * Two types of operations are provided for manipulating the scale of a
  33.  * BigDecimal: scaling/rounding operations and decimal point motion
  34.  * operations.  Scaling/rounding operations (<tt>SetScale</tt>) return a
  35.  * BigDecimal whose value is approximately (or exactly) equal to that of the
  36.  * operand, but whose scale is the specified value; that is, they increase or
  37.  * decrease the precision of the number with minimal effect on its value.
  38.  * Decimal point motion operations (<tt>movePointLeft</tt> and
  39.  * <tt>movePointRight</tt>) return a BigDecimal created from the operand by
  40.  * moving the decimal point a specified distance in the specified direction;
  41.  * that is, they change a number's value without affecting its precision.
  42.  * <p>
  43.  * For the sake of brevity and clarity, pseudo-code is used throughout the
  44.  * descriptions of BigDecimal methods.  The pseudo-code expression
  45.  * <tt>(i + j)</tt> is shorthand for "a BigDecimal whose value is
  46.  * that of the BigDecimal <tt>i</tt> plus that of the BigDecimal <tt>j</tt>."
  47.  * The pseudo-code expression <tt>(i == j)</tt> is shorthand for
  48.  * "<tt>true</tt> if and only if the BigDecimal <tt>i</tt> represents the same
  49.  * value as the the BigDecimal <tt>j</tt>."  Other pseudo-code expressions are
  50.  * interpreted similarly. 
  51.  * <p>
  52.  * Note: care should be exercised if BigDecimals are to be used as keys in a
  53.  * SortedMap or elements in a SortedSet, as BigDecimal's <i>natural
  54.  * ordering</i> is <i>inconsistent with equals</i>.  See Comparable, SortedMap
  55.  * or SortedSet for more information.
  56.  *
  57.  * @see     BigInteger
  58.  * @see        java.util.SortedMap
  59.  * @see        java.util.SortedSet
  60.  * @version 1.18, 99/03/26
  61.  * @author Josh Bloch
  62.  */
  63. public class BigDecimal extends Number implements Comparable {
  64.     /**
  65.      * The unscaled value of this BigDecimal, as returned by unscaledValue().
  66.      *
  67.      * @serial
  68.      * @see #unscaledValue
  69.      */
  70.     private BigInteger intVal;
  71.  
  72.     /**
  73.      * The scale of this BigDecimal, as returned by scale().
  74.      *
  75.      * @serial
  76.      * @see #scale
  77.      */
  78.     private int           scale = 0;
  79.  
  80.     /* Appease the serialization gods */
  81.     private static final long serialVersionUID = 6108874887143696463L;
  82.  
  83.     // Constructors
  84.  
  85.     /**
  86.      * Translates the String representation of a BigDecmal into a BigDecimal.
  87.      * The String representation consists of an optional minus sign followed
  88.      * by a sequence of zero or more decimal digits, optionally followed by a
  89.      * fraction.  The fraction consists of of a decimal point followed by zero
  90.      * or more decimal digits.  The string must contain at least one digit in
  91.      * the integer or fractional part.  The scale of the resulting BigDecimal
  92.      * will be the number of digits to the right of the decimal point in the
  93.      * string, or 0 if the string contains no decimal point.  The
  94.      * character-to-digit mapping is provided by Character.digit.  The String
  95.      * may not contain any extraneous characters (whitespace, for example).
  96.      *
  97.      * @param val String representation of BigDecimal.
  98.      * @throws NumberFormatException <tt>val</tt> is not a valid representation
  99.      *           of a BigDecimal.
  100.      * @see    Character#digit
  101.      */
  102.     public BigDecimal(String val) {
  103.     int pointPos = val.indexOf('.');
  104.     if (pointPos == -1) {             /* e.g. "123" */
  105.         intVal = new BigInteger(val);
  106.     } else if (pointPos == val.length()-1) { /* e.g. "123." */
  107.         intVal = new BigInteger(val.substring(0, val.length()-1));
  108.     } else {    /* Fraction part exists */
  109.         String fracString = val.substring(pointPos+1);
  110.         scale = fracString.length();
  111.         BigInteger fraction =  new BigInteger(fracString);
  112.         if (fraction.signum() < 0)         /* ".-123" illegal! */
  113.         throw new NumberFormatException();
  114.  
  115.         if (pointPos==0) {             /* e.g.  ".123" */
  116.         intVal = fraction;
  117.         } else if (val.charAt(0)=='-' && pointPos==1) {
  118.         intVal = fraction.negate();     /* e.g. "-.123" */
  119.         } else  {                 /* e.g. "-123.456" */
  120.         String intString = val.substring(0, pointPos);
  121.         BigInteger intPart = new BigInteger(intString);
  122.         if (val.charAt(0) == '-')
  123.             fraction = fraction.negate();
  124.         intVal = timesTenToThe(intPart, scale).add(fraction);
  125.         }
  126.     }
  127.     }
  128.  
  129.     /**
  130.      * Translates a double into a BigDecimal.  The scale of the BigDecimal
  131.      * is the smallest value such that <tt>(10<sup>scale</sup> * val)</tt>
  132.      * is an integer.
  133.      * <p>
  134.      * Note: the results of this constructor can be somewhat unpredictable.
  135.      * One might assume that <tt>new BigDecimal(.1)</tt> is exactly equal
  136.      * to .1, but it is actually equal
  137.      * to .1000000000000000055511151231257827021181583404541015625.
  138.      * This is so because .1 cannot be represented exactly as a double
  139.      * (or, for that matter, as a binary fraction of any finite length).
  140.      * Thus, the long value that is being passed <i>in</i> to the constructor is
  141.      * not exactly equal to .1, appearances nonwithstanding.
  142.      * <p>
  143.      * The (String) constructor, on the other hand, is perfectly predictable:
  144.      * <tt>new BigDecimal(".1")</tt> is <i>exactly</i> equal to .1, as one
  145.      * would expect.  Therefore, it is generally recommended that the (String)
  146.      * constructor be used in preference to this one.
  147.      *
  148.      * @param val double value to be converted to BigDecimal.
  149.      * @throws NumberFormatException <tt>val</tt> is equal to
  150.      *            <tt>Double.NEGATIVE_INFINITY</tt>,
  151.      *           <tt>Double.POSITIVE_INFINITY</tt>, or <tt>Double.NaN</tt>.
  152.      */
  153.     public BigDecimal(double val) {
  154.     if (Double.isInfinite(val) || Double.isNaN(val))
  155.         throw new NumberFormatException("Infinite or NaN");
  156.  
  157.     /*
  158.      * Translate the double into sign, exponent and mantissa, according
  159.      * to the formulae in JLS, Section 20.10.22.
  160.      */
  161.     long valBits = Double.doubleToLongBits(val);
  162.     int sign = ((valBits >> 63)==0 ? 1 : -1);
  163.     int exponent = (int) ((valBits >> 52) & 0x7ffL);
  164.     long mantissa = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
  165.                      : (valBits & ((1L<<52) - 1)) | (1L<<52));
  166.     exponent -= 1075;
  167.     /* At this point, val == sign * mantissa * 2**exponent */
  168.  
  169.     /*
  170.      * Special case zero to to supress nonterminating normalization
  171.      * and bogus scale calculation.
  172.      */
  173.     if (mantissa == 0) {
  174.         intVal = BigInteger.ZERO;
  175.         return;
  176.     }
  177.  
  178.     /* Normalize */
  179.     while((mantissa & 1) == 0) {    /*  i.e., Mantissa is even */
  180.         mantissa >>= 1;
  181.         exponent++;
  182.     }
  183.  
  184.     /* Calculate intVal and scale */
  185.     intVal = BigInteger.valueOf(sign*mantissa);
  186.     if (exponent < 0) {
  187.         intVal = intVal.multiply(BigInteger.valueOf(5).pow(-exponent));
  188.         scale = -exponent;
  189.     } else if (exponent > 0) {
  190.         intVal = intVal.multiply(BigInteger.valueOf(2).pow(exponent));
  191.     }
  192.     }
  193.  
  194.     /**
  195.      * Translates a BigInteger into a BigDecimal.  The scale of the BigDecimal
  196.      * is zero.
  197.      *
  198.      * @param val BigInteger value to be converted to BigDecimal.
  199.      */
  200.     public BigDecimal(BigInteger val) {
  201.     intVal = val;
  202.     }
  203.  
  204.     /**
  205.      * Translates a BigInteger unscaled value and an int scale into a
  206.      * BigDecimal.  The value of the BigDecimal is
  207.      * <tt>(unscaledVal/10<sup>scale</sup>)</tt>.
  208.      *
  209.      * @param unscaledVal unscaled value of the BigDecimal.
  210.      * @param scale scale of the BigDecimal.
  211.      * @throws NumberFormatException scale is negative
  212.      */
  213.     public BigDecimal(BigInteger unscaledVal, int scale) {
  214.     if (scale < 0)
  215.         throw new NumberFormatException("Negative scale");
  216.  
  217.     intVal = unscaledVal;
  218.     this.scale = scale;
  219.     }
  220.  
  221.  
  222.     // Static Factory Methods
  223.  
  224.     /**
  225.      * Translates a long unscaled value and an int scale into a BigDecimal.
  226.      * This "static factory method" is provided in preference to a
  227.      * (long, int) constructor because it allows for reuse of frequently used
  228.      * BigDecimals.
  229.      *
  230.      * @param unscaledVal unscaled value of the BigDecimal.
  231.      * @param scale scale of the BigDecimal.
  232.      * @return a BigDecimal whose value is
  233.      *           <tt>(unscaledVal/10<sup>scale</sup>)</tt>.
  234.      */
  235.     public static BigDecimal valueOf(long unscaledVal, int scale) {
  236.     return new BigDecimal(BigInteger.valueOf(unscaledVal), scale);
  237.     }
  238.  
  239.     /**
  240.      * Translates a long value into a BigDecimal with a scale of zero.
  241.      * This "static factory method" is provided in preference to a
  242.      * (long) constructor because it allows for reuse of frequently
  243.      * used BigDecimals.
  244.      *
  245.      * @param val value of the BigDecimal.
  246.      * @return a BigDecimal whose value is <tt>val</tt>.
  247.      */
  248.     public static BigDecimal valueOf(long val) {
  249.     return valueOf(val, 0);
  250.     }
  251.  
  252.  
  253.     // Arithmetic Operations
  254.  
  255.     /**
  256.      * Returns a BigDecimal whose value is <tt>(this + val)</tt>, and whose
  257.      * scale is <tt>max(this.scale(), val.scale())</tt>.
  258.      *
  259.      * @param  val value to be added to this BigDecimal.
  260.      * @return <tt>this + val</tt>
  261.      */
  262.     public BigDecimal add(BigDecimal val){
  263.     BigDecimal arg[] = new BigDecimal[2];
  264.     arg[0] = this;    arg[1] = val;
  265.     matchScale(arg);
  266.     return new BigDecimal(arg[0].intVal.add(arg[1].intVal), arg[0].scale);
  267.     }
  268.  
  269.     /**
  270.      * Returns a BigDecimal whose value is <tt>(this - val)</tt>, and whose
  271.      * scale is <tt>max(this.scale(), val.scale())</tt>.
  272.      *
  273.      * @param  val value to be subtracted from this BigDecimal.
  274.      * @return <tt>this - val</tt>
  275.      */
  276.     public BigDecimal subtract(BigDecimal val){
  277.     BigDecimal arg[] = new BigDecimal[2];
  278.     arg[0] = this;    arg[1] = val;
  279.     matchScale(arg);
  280.     return new BigDecimal(arg[0].intVal.subtract(arg[1].intVal),
  281.                   arg[0].scale);
  282.     }
  283.  
  284.     /**
  285.      * Returns a BigDecimal whose value is <tt>(this * val)</tt>, and whose
  286.      * scale is <tt>(this.scale() + val.scale())</tt>.
  287.      *
  288.      * @param  val value to be multiplied by this BigDecimal.
  289.      * @return <tt>this * val</tt>
  290.      */
  291.     public BigDecimal multiply(BigDecimal val){
  292.     return new BigDecimal(intVal.multiply(val.intVal), scale+val.scale);
  293.     }
  294.  
  295.     /**
  296.      * Returns a BigDecimal whose value is <tt>(this / val)</tt>, and whose
  297.      * scale is as specified.  If rounding must be performed to generate a
  298.      * result with the specified scale, the specified rounding mode is
  299.      * applied.
  300.      *
  301.      * @param  val value by which this BigDecimal is to be divided.
  302.      * @param  scale scale of the BigDecimal quotient to be returned.
  303.      * @param  roundingMode rounding mode to apply.
  304.      * @return <tt>this / val</tt>
  305.      * @throws ArithmeticException <tt>val</tt> is zero, <tt>scale</tt> is
  306.      *           negative, or <tt>roundingMode==ROUND_UNNECESSARY</tt> and
  307.      *           the specified scale is insufficient to represent the result
  308.      *           of the division exactly.
  309.      * @throws IllegalArgumentException <tt>roundingMode</tt> does not
  310.      *           represent a valid rounding mode.
  311.      * @see    #ROUND_UP
  312.      * @see    #ROUND_DOWN
  313.      * @see    #ROUND_CEILING
  314.      * @see    #ROUND_FLOOR
  315.      * @see    #ROUND_HALF_UP
  316.      * @see    #ROUND_HALF_DOWN
  317.      * @see    #ROUND_HALF_EVEN
  318.      * @see    #ROUND_UNNECESSARY
  319.      */
  320.     public BigDecimal divide(BigDecimal val, int scale, int roundingMode) {
  321.     if (scale < 0)
  322.         throw new ArithmeticException("Negative scale");
  323.     if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
  324.         throw new IllegalArgumentException("Invalid rounding mode");
  325.  
  326.     /*
  327.      * Rescale dividend or divisor (whichever can be "upscaled" to
  328.      * produce correctly scaled quotient).
  329.      */
  330.     BigDecimal dividend, divisor;
  331.     if (scale + val.scale >= this.scale) {
  332.         dividend = this.setScale(scale + val.scale);
  333.         divisor = val;
  334.     } else {
  335.         dividend = this;
  336.         divisor = val.setScale(this.scale - scale);
  337.     }
  338.  
  339.     /* Do the division and return result if it's exact */
  340.     BigInteger i[] = dividend.intVal.divideAndRemainder(divisor.intVal);
  341.     BigInteger q = i[0], r = i[1];
  342.     if (r.signum() == 0)
  343.         return new BigDecimal(q, scale);
  344.     else if (roundingMode == ROUND_UNNECESSARY) /* Rounding prohibited */
  345.         throw new ArithmeticException("Rounding necessary");
  346.  
  347.     /* Round as appropriate */
  348.     int signum = dividend.signum() * divisor.signum(); /* Sign of result */
  349.     boolean increment;
  350.     if (roundingMode == ROUND_UP) {            /* Away from zero */
  351.         increment = true;
  352.     } else if (roundingMode == ROUND_DOWN) {    /* Towards zero */
  353.         increment = false;
  354.     } else if (roundingMode == ROUND_CEILING) { /* Towards +infinity */
  355.         increment = (signum > 0);
  356.     } else if (roundingMode == ROUND_FLOOR) {   /* Towards -infinity */
  357.         increment = (signum < 0);
  358.     } else { /* Remaining modes based on nearest-neighbor determination */
  359.         int cmpFracHalf = r.abs().multiply(BigInteger.valueOf(2)).
  360.                      compareTo(divisor.intVal.abs());
  361.         if (cmpFracHalf < 0) {       /* We're closer to higher digit */
  362.         increment = false;
  363.         } else if (cmpFracHalf > 0) {  /* We're closer to lower digit */
  364.         increment = true;
  365.         } else {                /* We're dead-center */
  366.         if (roundingMode == ROUND_HALF_UP)
  367.             increment = true;
  368.         else if (roundingMode == ROUND_HALF_DOWN)
  369.             increment = false;
  370.         else  /* roundingMode == ROUND_HALF_EVEN */
  371.             increment = q.testBit(0);    /* true iff q is odd */
  372.         }
  373.     }
  374.     return (increment
  375.         ? new BigDecimal(q.add(BigInteger.valueOf(signum)), scale)
  376.         : new BigDecimal(q, scale));
  377.     }
  378.  
  379.     /**
  380.      * Returns a BigDecimal whose value is <tt>(this / val)</tt>, and whose
  381.      * scale is <tt>this.scale()</tt>.  If rounding must be performed to
  382.      * generate a result with the given scale, the specified rounding mode is
  383.      * applied.
  384.      *
  385.      * @param  val value by which this BigDecimal is to be divided.
  386.      * @param  roundingMode rounding mode to apply.
  387.      * @return <tt>this / val</tt>
  388.      * @throws ArithmeticException <tt>val==0</tt>, or
  389.      *            <tt>roundingMode==ROUND_UNNECESSARY</tt> and
  390.      *           <tt>this.scale()</tt> is insufficient to represent the result
  391.      *           of the division exactly. 
  392.      * @throws IllegalArgumentException <tt>roundingMode</tt> does not
  393.      *           represent a valid rounding mode.
  394.      * @see    #ROUND_UP
  395.      * @see    #ROUND_DOWN
  396.      * @see    #ROUND_CEILING
  397.      * @see    #ROUND_FLOOR
  398.      * @see    #ROUND_HALF_UP
  399.      * @see    #ROUND_HALF_DOWN
  400.      * @see    #ROUND_HALF_EVEN
  401.      * @see    #ROUND_UNNECESSARY
  402.      */
  403.     public BigDecimal divide(BigDecimal val, int roundingMode) {
  404.         return this.divide(val, scale, roundingMode);
  405.     }
  406.  
  407.    /**
  408.     * Returns a BigDecimal whose value is the absolute value of this
  409.     * BigDecimal, and whose scale is <tt>this.scale()</tt>.
  410.     *
  411.     * @return <tt>abs(this)</tt>
  412.     */
  413.     public BigDecimal abs(){
  414.     return (signum() < 0 ? negate() : this);
  415.     }
  416.  
  417.     /**
  418.      * Returns a BigDecimal whose value is <tt>(-this)</tt>, and whose scale
  419.      * is this.scale().
  420.      *
  421.      * @return <tt>-this</tt>
  422.      */
  423.     public BigDecimal negate(){
  424.     return new BigDecimal(intVal.negate(), scale);
  425.     }
  426.  
  427.     /**
  428.      * Returns the signum function of this BigDecimal.
  429.      *
  430.      * @return -1, 0 or 1 as the value of this BigDecimal is negative, zero or
  431.      *           positive.
  432.      */
  433.     public int signum(){
  434.     return intVal.signum();
  435.     }
  436.  
  437.     /**
  438.      * Returns the <i>scale</i> of this BigDecimal.  (The scale is the number
  439.      * of digits to the right of the decimal point.)
  440.      *
  441.      * @return the scale of this BigDecimal.
  442.      */
  443.     public int scale() {
  444.     return scale;
  445.     }
  446.  
  447.     /**
  448.      * Returns a BigInteger whose value is the <i>unscaled value</i> of this
  449.      * BigDecimal.  (Computes <tt>(this * 10<sup>this.scale()</sup>)</tt>.)
  450.      *
  451.      * @return the unscaled value of this BigDecimal.
  452.      * @since   JDK1.2
  453.      */
  454.     public BigInteger unscaledValue() {
  455.         return intVal;
  456.     }
  457.  
  458.  
  459.     // Rounding Modes
  460.  
  461.     /**
  462.      * Rounding mode to round away from zero.  Always increments the
  463.      * digit prior to a non-zero discarded fraction.  Note that this rounding
  464.      * mode never decreases the magnitude of the calculated value.
  465.      */
  466.     public final static int ROUND_UP =          0;
  467.  
  468.     /**
  469.      * Rounding mode to round towards zero.  Never increments the digit
  470.      * prior to a discarded fraction (i.e., truncates).  Note that this
  471.      * rounding mode never increases the magnitude of the calculated value.
  472.      */
  473.     public final static int ROUND_DOWN =      1;
  474.  
  475.     /**
  476.      * Rounding mode to round towards positive infinity.  If the
  477.      * BigDecimal is positive, behaves as for <tt>ROUND_UP</tt>; if negative, 
  478.      * behaves as for <tt>ROUND_DOWN</tt>.  Note that this rounding mode never
  479.      * decreases the calculated value.
  480.      */
  481.     public final static int ROUND_CEILING =      2;
  482.  
  483.     /**
  484.      * Rounding mode to round towards negative infinity.  If the
  485.      * BigDecimal is positive, behave as for <tt>ROUND_DOWN</tt>; if negative,
  486.      * behave as for <tt>ROUND_UP</tt>.  Note that this rounding mode never
  487.      * increases the calculated value.
  488.      */
  489.     public final static int ROUND_FLOOR =      3;
  490.  
  491.     /**
  492.      * Rounding mode to round towards "nearest neighbor" unless both
  493.      * neighbors are equidistant, in which case round up.
  494.      * Behaves as for <tt>ROUND_UP</tt> if the discarded fraction is >= .5;
  495.      * otherwise, behaves as for <tt>ROUND_DOWN</tt>.  Note that this is the
  496.      * rounding mode that most of us were taught in grade school.
  497.      */
  498.     public final static int ROUND_HALF_UP =      4;
  499.  
  500.     /**
  501.      * Rounding mode to round towards "nearest neighbor" unless both
  502.      * neighbors are equidistant, in which case round down.
  503.      * Behaves as for <tt>ROUND_UP</tt> if the discarded fraction is > .5;
  504.      * otherwise, behaves as for <tt>ROUND_DOWN</tt>.
  505.      */
  506.     public final static int ROUND_HALF_DOWN =      5;
  507.  
  508.     /**
  509.      * Rounding mode to round towards the "nearest neighbor" unless both
  510.      * neighbors are equidistant, in which case, round towards the even
  511.      * neighbor.  Behaves as for ROUND_HALF_UP if the digit to the left of the
  512.      * discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it's even.
  513.      * Note that this is the rounding mode that minimizes cumulative error
  514.      * when applied repeatedly over a sequence of calculations.
  515.      */
  516.     public final static int ROUND_HALF_EVEN =      6;
  517.  
  518.     /**
  519.      * Rounding mode to assert that the requested operation has an exact
  520.      * result, hence no rounding is necessary.  If this rounding mode is
  521.      * specified on an operation that yields an inexact result, an
  522.      * <tt>ArithmeticException</tt> is thrown.
  523.      */
  524.     public final static int ROUND_UNNECESSARY =  7;
  525.  
  526.  
  527.     // Scaling/Rounding Operations
  528.  
  529.     /**
  530.      * Returns a BigDecimal whose scale is the specified value, and whose
  531.      * unscaled value is determined by multiplying or dividing this
  532.      * BigDecimal's unscaled value by the appropriate power of ten to maintain
  533.      * its overall value.  If the scale is reduced by the operation, the
  534.      * unscaled value must be divided (rather than multiplied), and the value
  535.      * may be changed; in this case, the specified rounding mode is applied to
  536.      * the division.
  537.      *
  538.      * @param  scale scale of the BigDecimal value to be returned.
  539.      * @return a BigDecimal whose scale is the specified value, and whose
  540.      *           unscaled value is determined by multiplying or dividing this
  541.      *            BigDecimal's unscaled value by the appropriate power of ten to
  542.      *           maintain its overall value.
  543.      * @throws ArithmeticException <tt>scale</tt> is negative, or
  544.      *            <tt>roundingMode==ROUND_UNNECESSARY</tt> and the specified
  545.      *           scaling operation would require rounding.
  546.      * @throws IllegalArgumentException <tt>roundingMode</tt> does not
  547.      *           represent a valid rounding mode.
  548.      * @see    #ROUND_UP
  549.      * @see    #ROUND_DOWN
  550.      * @see    #ROUND_CEILING
  551.      * @see    #ROUND_FLOOR
  552.      * @see    #ROUND_HALF_UP
  553.      * @see    #ROUND_HALF_DOWN
  554.      * @see    #ROUND_HALF_EVEN
  555.      * @see    #ROUND_UNNECESSARY
  556.      */
  557.     public BigDecimal setScale(int scale, int roundingMode) {
  558.     if (scale < 0)
  559.         throw new ArithmeticException("Negative scale");
  560.     if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
  561.         throw new IllegalArgumentException("Invalid rounding mode");
  562.  
  563.     /* Handle the easy cases */
  564.     if (scale == this.scale)
  565.         return this;
  566.     else if (scale > this.scale)
  567.         return new BigDecimal(timesTenToThe(intVal, scale-this.scale),
  568.                   scale);
  569.     else /* scale < this.scale */
  570.         return divide(valueOf(1), scale, roundingMode);
  571.     }
  572.  
  573.     /**
  574.      * Returns a BigDecimal whose scale is the specified value, and whose
  575.      * value is numerically equal to this BigDecimal's.  Throws an
  576.      * ArithmeticException if this is not possible.  This call is typically
  577.      * used to increase the scale, in which case it is guaranteed that there
  578.      * exists a BigDecimal of the specified scale and the correct value.  The
  579.      * call can also be used to reduce the scale if the caller knows that the
  580.      * BigDecimal has sufficiently many zeros at the end of its fractional
  581.      * part (i.e., factors of ten in its integer value) to allow for the
  582.      * rescaling without loss of precision.
  583.      * <p>
  584.      * Note that this call returns the same result as the two argument version
  585.      * of setScale, but saves the caller the trouble of specifying a rounding
  586.      * mode in cases where it is irrelevant.
  587.      *
  588.      * @param  scale scale of the BigDecimal value to be returned.
  589.      * @return a BigDecimal whose scale is the specified value, and whose
  590.      *           unscaled value is determined by multiplying or dividing this
  591.      *            BigDecimal's unscaled value by the appropriate power of ten to
  592.      *           maintain its overall value.
  593.      * @throws ArithmeticException <tt>scale</tt> is negative, or
  594.      *            the specified scaling operation would require rounding.
  595.      * @see    #setScale(int, int)
  596.      */
  597.     public BigDecimal setScale(int scale) {
  598.     return setScale(scale, ROUND_UNNECESSARY);
  599.     }
  600.  
  601.  
  602.     // Decimal Point Motion Operations
  603.  
  604.     /**
  605.      * Returns a BigDecimal which is equivalent to this one with the decimal
  606.      * point moved n places to the left.  If n is non-negative, the call merely
  607.      * adds n to the scale.  If n is negative, the call is equivalent to
  608.      * movePointRight(-n).  (The BigDecimal returned by this call has value
  609.      * <tt>(this * 10<sup>-n</sup>)</tt> and scale
  610.      * <tt>max(this.scale()+n, 0)</tt>.)
  611.      *
  612.      * @param  n number of places to move the decimal point to the left.
  613.      * @return a BigDecimal which is equivalent to this one with the decimal
  614.      *           point moved <tt>n</tt> places to the left.
  615.      */
  616.     public BigDecimal movePointLeft(int n){
  617.     return (n>=0 ? new BigDecimal(intVal, scale+n) : movePointRight(-n));
  618.     }
  619.  
  620.     /**
  621.  
  622.      * Moves the decimal point the specified number of places to the right.
  623.      * If this BigDecimal's scale is >= <tt>n</tt>, the call merely
  624.      * subtracts <tt>n</tt> from the scale; otherwise, it sets the scale to
  625.      * zero, and multiplies the integer value by
  626.      * <tt>10<sup>(n - this.scale)</sup></tt>.  If <tt>n</tt>
  627.      * is negative, the call is equivalent to <tt>movePointLeft(-n)</tt>. (The
  628.      * BigDecimal returned by this call has value
  629.      * <tt>(this * 10<sup>n</sup>)</tt> and scale
  630.      * <tt>max(this.scale()-n, 0)</tt>.)
  631.      *
  632.      * @param  n number of places to move the decimal point to the right.
  633.      * @return a BigDecimal which is equivalent to this one with the decimal
  634.      *         point moved <tt>n</tt> places to the right.
  635.      */
  636.     public BigDecimal movePointRight(int n){
  637.     return (scale >= n ? new BigDecimal(intVal, scale-n)
  638.                    : new BigDecimal(timesTenToThe(intVal, n-scale),0));
  639.     }
  640.  
  641.     // Comparison Operations
  642.  
  643.     /**
  644.      * Compares this BigDecimal with the specified BigDecimal.   Two
  645.      * BigDecimals that are equal in value but have a different scale (like
  646.      * 2.0 and 2.00) are considered equal by this method.  This method is
  647.      * provided in preference to individual methods for each of the six
  648.      * boolean comparison operators (<, ==, >, >=, !=, <=).  The
  649.      * suggested idiom for performing these comparisons is:
  650.      * <tt>(x.compareTo(y)</tt> <<i>op</i>> <tt>0)</tt>,
  651.      * where <<i>op</i>> is one of the six comparison operators.
  652.      *
  653.      * @param  val BigDecimal to which this BigDecimal is to be compared.
  654.      * @return -1, 0 or 1 as this BigDecimal is numerically less than, equal
  655.      *         to, or greater than <tt>val</tt>.
  656.      */
  657.     public int compareTo(BigDecimal val){
  658.     /* Optimization: would run fine without the next three lines */
  659.     int sigDiff = signum() - val.signum();
  660.     if (sigDiff != 0)
  661.         return (sigDiff > 0 ? 1 : -1);
  662.  
  663.     /* If signs match, scale and compare intVals */
  664.     BigDecimal arg[] = new BigDecimal[2];
  665.     arg[0] = this;    arg[1] = val;
  666.     matchScale(arg);
  667.     return arg[0].intVal.compareTo(arg[1].intVal);
  668.     }
  669.  
  670.     /**
  671.      * Compares this BigDecimal with the specified Object.  If the Object is a
  672.      * BigDecimal, this method behaves like <tt>compareTo(BigDecimal)</tt>.
  673.      * Otherwise, it throws a <tt>ClassCastException</tt> (as BigDecimals are
  674.      * comparable only to other BigDecimals).
  675.      *
  676.      * @param  o Object to which this BigDecimal is to be compared.
  677.      * @return a negative number, zero, or a positive number as this
  678.      *           BigDecimal is numerically less than, equal to, or greater
  679.      *           than <tt>o</tt>, which must be a BigDecimal.
  680.      * @throws ClassCastException <tt>o</tt> is not a BigDecimal.
  681.      * @see    #compareTo(java.math.BigDecimal)
  682.      * @see    Comparable
  683.      * @since  JDK1.2
  684.      */
  685.     public int compareTo(Object o) {
  686.     return compareTo((BigDecimal)o);
  687.     }
  688.  
  689.     /**
  690.      * Compares this BigDecimal with the specified Object for equality.
  691.      * Unlike compareTo, this method considers two BigDecimals equal only
  692.      * if they are equal in value and scale (thus 2.0 is not equal to 2.00
  693.      * when compared by this method).
  694.      *
  695.      * @param  o Object to which this BigDecimal is to be compared.
  696.      * @return <tt>true</tt> if and only if the specified Object is a
  697.      *           BigDecimal whose value and scale are equal to this BigDecimal's.
  698.      * @see    #compareTo(java.math.BigDecimal)
  699.      */
  700.     public boolean equals(Object x){
  701.     if (!(x instanceof BigDecimal))
  702.         return false;
  703.     BigDecimal xDec = (BigDecimal) x;
  704.  
  705.     return scale == xDec.scale && intVal.equals(xDec.intVal);
  706.     }
  707.  
  708.     /**
  709.      * Returns the minimum of this BigDecimal and <tt>val</tt>.
  710.      *
  711.      * @param  val value with with the minimum is to be computed.
  712.      * @return the BigDecimal whose value is the lesser of this BigDecimal and 
  713.      *           <tt>val</tt>.  If they are equal, as defined by the
  714.      *            <tt>compareTo</tt> method, either may be returned.
  715.      * @see    #compareTo(java.math.BigDecimal)
  716.      */
  717.     public BigDecimal min(BigDecimal val){
  718.     return (compareTo(val)<0 ? this : val);
  719.     }
  720.  
  721.     /**
  722.      * Returns the maximum of this BigDecimal and <tt>val</tt>.
  723.      *
  724.      * @param  val value with with the maximum is to be computed.
  725.      * @return the BigDecimal whose value is the greater of this BigDecimal
  726.      *           and <tt>val</tt>.  If they are equal, as defined by the
  727.      *            <tt>compareTo</tt> method, either may be returned.
  728.      * @see    #compareTo(java.math.BigDecimal)
  729.      */
  730.     public BigDecimal max(BigDecimal val){
  731.     return (compareTo(val)>0 ? this : val);
  732.     }
  733.  
  734.  
  735.     // Hash Function
  736.  
  737.     /**
  738.      * Returns the hash code for this BigDecimal.  Note that two BigDecimals
  739.      * that are numerically equal but differ in scale (like 2.0 and 2.00)
  740.      * will generally <i>not</i> have the same hash code.
  741.      *
  742.      * @return hash code for this BigDecimal.
  743.      */
  744.     public int hashCode() {
  745.     return 31*intVal.hashCode() + scale;
  746.     }
  747.  
  748.  
  749.     // Format Converters
  750.  
  751.     /**
  752.      * Returns the string representation of this BigDecimal.  The digit-to-
  753.      * character mapping provided by <tt>Character.forDigit</tt> is used.
  754.      * A leading minus sign is used to indicate sign, and the number of digits
  755.      * to the right of the decimal point is used to indicate scale.  (This
  756.      * representation is compatible with the (String) constructor.)
  757.      *
  758.      * @return String representation of this BigDecimal.
  759.      * @see    Character#forDigit
  760.      * @see    #BigDecimal(java.lang.String)
  761.      */
  762.     public String toString(){
  763.     if (scale == 0)    /* No decimal point */
  764.         return intVal.toString();
  765.  
  766.     /* Insert decimal point */
  767.     StringBuffer buf;
  768.     String intString = intVal.abs().toString();
  769.     int signum = signum();
  770.     int insertionPoint = intString.length() - scale;
  771.     if (insertionPoint == 0) {  /* Point goes right before intVal */
  772.         return (signum<0 ? "-0." : "0.") + intString;
  773.     } else if (insertionPoint > 0) { /* Point goes inside intVal */
  774.         buf = new StringBuffer(intString);
  775.         buf.insert(insertionPoint, '.');
  776.         if (signum < 0)
  777.         buf.insert(0, '-');
  778.     } else { /* We must insert zeros between point and intVal */
  779.         buf = new StringBuffer(3-insertionPoint + intString.length());
  780.         buf.append(signum<0 ? "-0." : "0.");
  781.         for (int i=0; i<-insertionPoint; i++)
  782.         buf.append('0');
  783.         buf.append(intString);
  784.     }
  785.     return buf.toString();
  786.     }
  787.  
  788.     /**
  789.      * Converts this BigDecimal to a BigInteger.  Standard <i>narrowing
  790.      * primitive conversion</i> as defined in <i>The Java Language
  791.      * Specification</i>: any fractional part of this BigDecimal will be
  792.      * discarded.
  793.      *
  794.      * @return this BigDecimal converted to a BigInteger.
  795.      */
  796.     public BigInteger toBigInteger() {
  797.     return (scale==0 ? intVal
  798.              : intVal.divide(BigInteger.valueOf(10).pow(scale)));
  799.     }
  800.  
  801.     /**
  802.      * Converts this BigDecimal to an int.  Standard <i>narrowing primitive
  803.      * conversion</i> as defined in <i>The Java Language Specification</i>:
  804.      * any fractional part of this BigDecimal will be discarded, and if the
  805.      * resulting "BigInteger" is too big to fit in an int, only the low-order
  806.      * 32 bits are returned.
  807.      * 
  808.      * @return this BigDecimal converted to an int.
  809.      */
  810.     public int intValue(){
  811.     return toBigInteger().intValue();
  812.     }
  813.  
  814.     /**
  815.      * Converts this BigDecimal to a long.  Standard <i>narrowing primitive
  816.      * conversion</i> as defined in <i>The Java Language Specification</i>:
  817.      * any fractional part of this BigDecimal will be discarded, and if the
  818.      * resulting "BigInteger" is too big to fit in a long, only the low-order
  819.      * 64 bits are returned.
  820.      * 
  821.      * @return this BigDecimal converted to an int.
  822.      */
  823.     public long longValue(){
  824.     return toBigInteger().longValue();
  825.     }
  826.  
  827.     /**
  828.      * Converts this BigDecimal to a float.  Similar to the double-to-float
  829.      * <i>narrowing primitive conversion</i> defined in <i>The Java Language
  830.      * Specification</i>: if this BigDecimal has too great a magnitude to
  831.      * represent as a float, it will be converted to
  832.      * <tt>FLOAT.NEGATIVE_INFINITY</tt> or <tt>FLOAT.POSITIVE_INFINITY</tt>
  833.      * as appropriate.
  834.      * 
  835.      * @return this BigDecimal converted to a float.
  836.      */
  837.     public float floatValue(){
  838.     /* Somewhat inefficient, but guaranteed to work. */
  839.     return Float.valueOf(this.toString()).floatValue();
  840.     }
  841.  
  842.     /**
  843.      * Converts this BigDecimal to a double.  Similar to the double-to-float
  844.      * <i>narrowing primitive conversion</i> defined in <i>The Java Language
  845.      * Specification</i>: if this BigDecimal has too great a magnitude to
  846.      * represent as a double, it will be converted to
  847.      * <tt>DOUBLE.NEGATIVE_INFINITY</tt> or <tt>DOUBLE.POSITIVE_INFINITY</tt>
  848.      * as appropriate.
  849.      * 
  850.      * @return this BigDecimal converted to a double.
  851.      */
  852.     public double doubleValue(){
  853.     /* Somewhat inefficient, but guaranteed to work. */
  854.     return Double.valueOf(this.toString()).doubleValue();
  855.     }
  856.  
  857.  
  858.     // Private "Helper" Methods
  859.  
  860.     /* Returns (a * 10^b) */
  861.     private static BigInteger timesTenToThe(BigInteger a, int b) {
  862.     return a.multiply(BigInteger.valueOf(10).pow(b));
  863.     }
  864.  
  865.     /*
  866.      * If the scales of val[0] and val[1] differ, rescale (non-destructively)
  867.      * the lower-scaled BigDecimal so they match.
  868.      */
  869.     private static void matchScale(BigDecimal[] val) {
  870.     if (val[0].scale < val[1].scale)
  871.         val[0] = val[0].setScale(val[1].scale);
  872.     else if (val[1].scale < val[0].scale)
  873.         val[1] = val[1].setScale(val[0].scale);
  874.     }
  875.  
  876.     /**
  877.      * Reconstitute the <tt>BigDecimal</tt> instance from a stream (that is,
  878.      * deserialize it).
  879.      */
  880.     private synchronized void readObject(java.io.ObjectInputStream s)
  881.         throws java.io.IOException, ClassNotFoundException {
  882.         // Read in all fields
  883.     s.defaultReadObject();
  884.  
  885.         // Validate scale factor
  886.         if (scale < 0)
  887.         throw new java.io.StreamCorruptedException(
  888.                                       "BigDecimal: Negative scale");
  889.     }
  890. }
  891.