📄 bigdecimal.java
字号:
* @param val value of the BigDecimal. * @return a BigDecimal whose value is <tt>val</tt>. */ public static BigDecimal valueOf(long val) { return valueOf(val, 0); } // Arithmetic Operations /** * Returns a BigDecimal whose value is <tt>(this + val)</tt>, and whose * scale is <tt>max(this.scale(), val.scale())</tt>. * * @param val value to be added to this BigDecimal. * @return <tt>this + val</tt> */ public BigDecimal add(BigDecimal val){ BigDecimal arg[] = new BigDecimal[2]; arg[0] = this; arg[1] = val; matchScale(arg); return new BigDecimal(arg[0].intVal.add(arg[1].intVal), arg[0].scale); } /** * Returns a BigDecimal whose value is <tt>(this - val)</tt>, and whose * scale is <tt>max(this.scale(), val.scale())</tt>. * * @param val value to be subtracted from this BigDecimal. * @return <tt>this - val</tt> */ public BigDecimal subtract(BigDecimal val){ BigDecimal arg[] = new BigDecimal[2]; arg[0] = this; arg[1] = val; matchScale(arg); return new BigDecimal(arg[0].intVal.subtract(arg[1].intVal), arg[0].scale); } /** * Returns a BigDecimal whose value is <tt>(this * val)</tt>, and whose * scale is <tt>(this.scale() + val.scale())</tt>. * * @param val value to be multiplied by this BigDecimal. * @return <tt>this * val</tt> */ public BigDecimal multiply(BigDecimal val){ return new BigDecimal(intVal.multiply(val.intVal), scale+val.scale); } /** * Returns a BigDecimal whose value is <tt>(this / val)</tt>, and whose * scale is as specified. If rounding must be performed to generate a * result with the specified scale, the specified rounding mode is * applied. * * @param val value by which this BigDecimal is to be divided. * @param scale scale of the BigDecimal quotient to be returned. * @param roundingMode rounding mode to apply. * @return <tt>this / val</tt> * @throws ArithmeticException <tt>val</tt> is zero, <tt>scale</tt> is * negative, or <tt>roundingMode==ROUND_UNNECESSARY</tt> and * the specified scale is insufficient to represent the result * of the division exactly. * @throws IllegalArgumentException <tt>roundingMode</tt> does not * represent a valid rounding mode. * @see #ROUND_UP * @see #ROUND_DOWN * @see #ROUND_CEILING * @see #ROUND_FLOOR * @see #ROUND_HALF_UP * @see #ROUND_HALF_DOWN * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ public BigDecimal divide(BigDecimal val, int scale, int roundingMode) { if (scale < 0) throw new ArithmeticException("Negative scale"); if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); /* * Rescale dividend or divisor (whichever can be "upscaled" to * produce correctly scaled quotient). */ BigDecimal dividend, divisor; if (scale + val.scale >= this.scale) { dividend = this.setScale(scale + val.scale); divisor = val; } else { dividend = this; divisor = val.setScale(this.scale - scale); } /* Do the division and return result if it's exact */ BigInteger i[] = dividend.intVal.divideAndRemainder(divisor.intVal); BigInteger q = i[0], r = i[1]; if (r.signum() == 0) return new BigDecimal(q, scale); else if (roundingMode == ROUND_UNNECESSARY) /* Rounding prohibited */ throw new ArithmeticException("Rounding necessary"); /* Round as appropriate */ int signum = dividend.signum() * divisor.signum(); /* Sign of result */ boolean increment; if (roundingMode == ROUND_UP) { /* Away from zero */ increment = true; } else if (roundingMode == ROUND_DOWN) { /* Towards zero */ increment = false; } else if (roundingMode == ROUND_CEILING) { /* Towards +infinity */ increment = (signum > 0); } else if (roundingMode == ROUND_FLOOR) { /* Towards -infinity */ increment = (signum < 0); } else { /* Remaining modes based on nearest-neighbor determination */ int cmpFracHalf = r.abs().multiply(BigInteger.valueOf(2)). compareTo(divisor.intVal.abs()); if (cmpFracHalf < 0) { /* We're closer to higher digit */ increment = false; } else if (cmpFracHalf > 0) { /* We're closer to lower digit */ increment = true; } else { /* We're dead-center */ if (roundingMode == ROUND_HALF_UP) increment = true; else if (roundingMode == ROUND_HALF_DOWN) increment = false; else /* roundingMode == ROUND_HALF_EVEN */ increment = q.testBit(0); /* true iff q is odd */ } } return (increment ? new BigDecimal(q.add(BigInteger.valueOf(signum)), scale) : new BigDecimal(q, scale)); } /** * Returns a BigDecimal whose value is <tt>(this / val)</tt>, and whose * scale is <tt>this.scale()</tt>. If rounding must be performed to * generate a result with the given scale, the specified rounding mode is * applied. * * @param val value by which this BigDecimal is to be divided. * @param roundingMode rounding mode to apply. * @return <tt>this / val</tt> * @throws ArithmeticException <tt>val==0</tt>, or * <tt>roundingMode==ROUND_UNNECESSARY</tt> and * <tt>this.scale()</tt> is insufficient to represent the result * of the division exactly. * @throws IllegalArgumentException <tt>roundingMode</tt> does not * represent a valid rounding mode. * @see #ROUND_UP * @see #ROUND_DOWN * @see #ROUND_CEILING * @see #ROUND_FLOOR * @see #ROUND_HALF_UP * @see #ROUND_HALF_DOWN * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ public BigDecimal divide(BigDecimal val, int roundingMode) { return this.divide(val, scale, roundingMode); } /** * Returns a BigDecimal whose value is the absolute value of this * BigDecimal, and whose scale is <tt>this.scale()</tt>. * * @return <tt>abs(this)</tt> */ public BigDecimal abs(){ return (signum() < 0 ? negate() : this); } /** * Returns a BigDecimal whose value is <tt>(-this)</tt>, and whose scale * is <tt>this.scale()</tt>. * * @return <tt>-this</tt> */ public BigDecimal negate(){ return new BigDecimal(intVal.negate(), scale); } /** * Returns the signum function of this BigDecimal. * * @return -1, 0 or 1 as the value of this BigDecimal is negative, zero or * positive. */ public int signum(){ return intVal.signum(); } /** * Returns the <i>scale</i> of this BigDecimal. (The scale is the number * of digits to the right of the decimal point.) * * @return the scale of this BigDecimal. */ public int scale() { return scale; } /** * Returns a BigInteger whose value is the <i>unscaled value</i> of this * BigDecimal. (Computes <tt>(this * 10<sup>this.scale()</sup>)</tt>.) * * @return the unscaled value of this BigDecimal. * @since 1.2 */ public BigInteger unscaledValue() { return intVal; } // Rounding Modes /** * Rounding mode to round away from zero. Always increments the * digit prior to a non-zero discarded fraction. Note that this rounding * mode never decreases the magnitude of the calculated value. */ public final static int ROUND_UP = 0; /** * Rounding mode to round towards zero. Never increments the digit * prior to a discarded fraction (i.e., truncates). Note that this * rounding mode never increases the magnitude of the calculated value. */ public final static int ROUND_DOWN = 1; /** * Rounding mode to round towards positive infinity. If the * BigDecimal is positive, behaves as for <tt>ROUND_UP</tt>; if negative, * behaves as for <tt>ROUND_DOWN</tt>. Note that this rounding mode never * decreases the calculated value. */ public final static int ROUND_CEILING = 2; /** * Rounding mode to round towards negative infinity. If the * BigDecimal is positive, behave as for <tt>ROUND_DOWN</tt>; if negative, * behave as for <tt>ROUND_UP</tt>. Note that this rounding mode never * increases the calculated value. */ public final static int ROUND_FLOOR = 3; /** * Rounding mode to round towards "nearest neighbor" unless both * neighbors are equidistant, in which case round up. * Behaves as for <tt>ROUND_UP</tt> if the discarded fraction is >= .5; * otherwise, behaves as for <tt>ROUND_DOWN</tt>. Note that this is the * rounding mode that most of us were taught in grade school. */ public final static int ROUND_HALF_UP = 4; /** * Rounding mode to round towards "nearest neighbor" unless both * neighbors are equidistant, in which case round down. * Behaves as for <tt>ROUND_UP</tt> if the discarded fraction is > .5; * otherwise, behaves as for <tt>ROUND_DOWN</tt>. */ public final static int ROUND_HALF_DOWN = 5; /** * Rounding mode to round towards the "nearest neighbor" unless both * neighbors are equidistant, in which case, round towards the even * neighbor. Behaves as for ROUND_HALF_UP if the digit to the left of the * discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it's even. * Note that this is the rounding mode that minimizes cumulative error * when applied repeatedly over a sequence of calculations. */ public final static int ROUND_HALF_EVEN = 6; /** * Rounding mode to assert that the requested operation has an exact * result, hence no rounding is necessary. If this rounding mode is * specified on an operation that yields an inexact result, an * <tt>ArithmeticException</tt> is thrown. */ public final static int ROUND_UNNECESSARY = 7; // Scaling/Rounding Operations /** * Returns a BigDecimal whose scale is the specified value, and whose * unscaled value is determined by multiplying or dividing this * BigDecimal's unscaled value by the appropriate power of ten to maintain * its overall value. If the scale is reduced by the operation, the * unscaled value must be divided (rather than multiplied), and the value * may be changed; in this case, the specified rounding mode is applied to * the division. * <p> * Note that since BigDecimal objects are immutable, calls of this * method do <i>not</i> result in the original object being * modified, contrary to the usual convention of having methods * named <code>set<i>X</i></code> mutate field * <code><i>X</i></code>. Instead, <code>setScale</code> returns * an object with the proper scale; the returned object may or may * not be newly allocated. * * @param scale scale of the BigDecimal value to be returned. * @param roundingMode The rounding mode to apply. * @return a BigDecimal whose scale is the specified value, and whose * unscaled value is determined by multiplying or dividing this * BigDecimal's unscaled value by the appropriate power of ten to * maintain its overall value. * @throws ArithmeticException <tt>scale</tt> is negative, or * <tt>roundingMode==ROUND_UNNECESSARY</tt> and the specified * scaling operation would require rounding. * @throws IllegalArgumentException <tt>roundingMode</tt> does not * represent a valid rounding mode. * @see #ROUND_UP * @see #ROUND_DOWN * @see #ROUND_CEILING * @see #ROUND_FLOOR * @see #ROUND_HALF_UP * @see #ROUND_HALF_DOWN * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ public BigDecimal setScale(int scale, int roundingMode) { if (scale < 0) throw new ArithmeticException("Negative scale"); if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); /* Handle the easy cases */ if (scale == this.scale) return this; else if (scale > this.scale) return new BigDecimal(timesTenToThe(intVal, scale-this.scale), scale); else /* scale < this.scale */ return divide(valueOf(1), scale, roundingMode); } /** * Returns a BigDecimal whose scale is the specified value, and whose * value is numerically equal to this BigDecimal's. Throws an * ArithmeticException if this is not possible. This call is typically * used to increase the scale, in which case it is guaranteed that there * exists a BigDecimal of the specified scale and the correct value. The * call can also be used to reduce the scale if the caller knows that the * BigDecimal has sufficiently many zeros at the end of its fractional * part (i.e., factors of ten in its integer value) to allow for the * rescaling without loss of precision. * <p> * This method returns the same result as the two argument version * of setScale, but saves the caller the trouble of specifying a * rounding mode in cases where it is irrelevant. * <p> * Note that since BigDecimal objects are immutable, calls of this * method do <i>not</i> result in the original object being * modified, contrary to the usual convention of having methods * named <code>set<i>X</i></code> mutate field * <code><i>X</i></code>. Instead, <code>setScale</code> returns * an object with the proper scale; the returned object may or may * not be newly allocated. * * @param scale scale of the BigDecimal value to be returned. * @return a BigDecimal whose scale is the specified value, and whose * unscaled value is determined by multiplying or dividing this * BigDecimal's unscaled value by the appropriate power of ten to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -