📄 floatmul.java
字号:
* @param val <tt>double</tt> to convert to a <tt>BigDecimal</tt>. * @return a <tt>BigDecimal</tt> whose value is equal to or approximately * equal to the value of <tt>val</tt>. * @throws NumberFormatException if <tt>val</tt> is infinite or NaN. * @since 1.5 */ public static BigDecimal valueOf(double val) { // Reminder: a zero double returns '0.0', so we cannot fastpath // to use the constant ZERO. This might be important enough to // justify a factory approach, a cache, or a few private // constants, later. return new BigDecimal(Double.toString(val)); } // Arithmetic Operations /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this + * augend)</tt>, and whose scale is <tt>max(this.scale(), * augend.scale())</tt>. * * @param augend value to be added to this <tt>BigDecimal</tt>. * @return <tt>this + augend</tt> */ public BigDecimal add(BigDecimal augend) { BigDecimal arg[] = {this, augend}; matchScale(arg); long x = arg[0].intCompact; long y = arg[1].intCompact; // Might be able to do a more clever check incorporating the // inflated check into the overflow computation. if (x != INFLATED && y != INFLATED) { long sum = x + y; /* * If the sum is not an overflowed value, continue to use * the compact representation. if either of x or y is * INFLATED, the sum should also be regarded as an * overflow. See "Hacker's Delight" section 2-12 for * explanation of the overflow test. */ if ( (((sum ^ x) & (sum ^ y)) >> 63) == 0L ) // not overflowed return BigDecimal.valueOf(sum, arg[0].scale); } return new BigDecimal(arg[0].inflate().intVal.add(arg[1].inflate().intVal), arg[0].scale); } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this + augend)</tt>, * with rounding according to the context settings. * * If either number is zero and the precision setting is nonzero then * the other number, rounded if necessary, is used as the result. * * @param augend value to be added to this <tt>BigDecimal</tt>. * @param mc the context to use. * @return <tt>this + augend</tt>, rounded as necessary. * @throws ArithmeticException if the result is inexact but the * rounding mode is <tt>UNNECESSARY</tt>. * @since 1.5 */ public BigDecimal add(BigDecimal augend, MathContext mc) { if (mc.precision == 0) return add(augend); BigDecimal lhs = this; // Could optimize if values are compact this.inflate(); augend.inflate(); // If either number is zero then the other number, rounded and // scaled if necessary, is used as the result. { boolean lhsIsZero = lhs.signum() == 0; boolean augendIsZero = augend.signum() == 0; if (lhsIsZero || augendIsZero) { int preferredScale = Math.max(lhs.scale(), augend.scale()); BigDecimal result; // Could use a factory for zero instead of a new object if (lhsIsZero && augendIsZero) return new BigDecimal(BigInteger.ZERO, 0, preferredScale); result = lhsIsZero ? augend.doRound(mc) : lhs.doRound(mc); if (result.scale() == preferredScale) return result; else if (result.scale() > preferredScale) return new BigDecimal(result.intVal, result.intCompact, result.scale). stripZerosToMatchScale(preferredScale); else { // result.scale < preferredScale int precisionDiff = mc.precision - result.precision(); int scaleDiff = preferredScale - result.scale(); if (precisionDiff >= scaleDiff) return result.setScale(preferredScale); // can achieve target scale else return result.setScale(result.scale() + precisionDiff); } } } long padding = (long)lhs.scale - augend.scale; if (padding != 0) { // scales differ; alignment needed BigDecimal arg[] = preAlign(lhs, augend, padding, mc); matchScale(arg); lhs = arg[0]; augend = arg[1]; } return new BigDecimal(lhs.inflate().intVal.add(augend.inflate().intVal), lhs.scale).doRound(mc); } /** * Returns an array of length two, the sum of whose entries is * equal to the rounded sum of the {@code BigDecimal} arguments. * * <p>If the digit positions of the arguments have a sufficient * gap between them, the value smaller in magnitude can be * condensed into a "sticky bit" and the end result will * round the same way <em>if</em> the precision of the final * result does not include the high order digit of the small * magnitude operand. * * <p>Note that while strictly speaking this is an optimization, * it makes a much wider range of additions practical. * * <p>This corresponds to a pre-shift operation in a fixed * precision floating-point adder; this method is complicated by * variable precision of the result as determined by the * MathContext. A more nuanced operation could implement a * "right shift" on the smaller magnitude operand so * that the number of digits of the smaller operand could be * reduced even though the significands partially overlapped. */ private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend, long padding, MathContext mc) { assert padding != 0; BigDecimal big; BigDecimal small; if (padding < 0) { // lhs is big; augend is small big = lhs; small = augend; } else { // lhs is small; augend is big big = augend; small = lhs; } /* * This is the estimated scale of an ulp of the result; it * assumes that the result doesn't have a carry-out on a true * add (e.g. 999 + 1 => 1000) or any subtractive cancellation * on borrowing (e.g. 100 - 1.2 => 98.8) */ long estResultUlpScale = (long)big.scale - big.precision() + mc.precision; /* * The low-order digit position of big is big.scale(). This * is true regardless of whether big has a positive or * negative scale. The high-order digit position of small is * small.scale - (small.precision() - 1). To do the full * condensation, the digit positions of big and small must be * disjoint *and* the digit positions of small should not be * directly visible in the result. */ long smallHighDigitPos = (long)small.scale - small.precision() + 1; if (smallHighDigitPos > big.scale + 2 && // big and small disjoint smallHighDigitPos > estResultUlpScale + 2) { // small digits not visible small = BigDecimal.valueOf(small.signum(), this.checkScale(Math.max(big.scale, estResultUlpScale) + 3)); } // Since addition is symmetric, preserving input order in // returned operands doesn't matter BigDecimal[] result = {big, small}; return result; } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this - * subtrahend)</tt>, and whose scale is <tt>max(this.scale(), * subtrahend.scale())</tt>. * * @param subtrahend value to be subtracted from this <tt>BigDecimal</tt>. * @return <tt>this - subtrahend</tt> */ public BigDecimal subtract(BigDecimal subtrahend) { BigDecimal arg[] = {this, subtrahend}; matchScale(arg); long x = arg[0].intCompact; long y = arg[1].intCompact; // Might be able to do a more clever check incorporating the // inflated check into the overflow computation. if (x != INFLATED && y != INFLATED) { long difference = x - y; /* * If the difference is not an overflowed value, continue * to use the compact representation. if either of x or y * is INFLATED, the difference should also be regarded as * an overflow. See "Hacker's Delight" section 2-12 for * explanation of the overflow test. */ if ( ((x ^ y) & (difference ^ x) ) >> 63 == 0L ) // not overflowed return BigDecimal.valueOf(difference, arg[0].scale); } return new BigDecimal(arg[0].inflate().intVal.subtract(arg[1].inflate().intVal), arg[0].scale); } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this - subtrahend)</tt>, * with rounding according to the context settings. * * If <tt>subtrahend</tt> is zero then this, rounded if necessary, is used as the * result. If this is zero then the result is <tt>subtrahend.negate(mc)</tt>. * * @param subtrahend value to be subtracted from this <tt>BigDecimal</tt>. * @param mc the context to use. * @return <tt>this - subtrahend</tt>, rounded as necessary. * @throws ArithmeticException if the result is inexact but the * rounding mode is <tt>UNNECESSARY</tt>. * @since 1.5 */ public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) { if (mc.precision == 0) return subtract(subtrahend); // share the special rounding code in add() this.inflate(); subtrahend.inflate(); BigDecimal rhs = new BigDecimal(subtrahend.intVal.negate(), subtrahend.scale); rhs.precision = subtrahend.precision; return add(rhs, mc); } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this × * multiplicand)</tt>, and whose scale is <tt>(this.scale() + * multiplicand.scale())</tt>. * * @param multiplicand value to be multiplied by this <tt>BigDecimal</tt>. * @return <tt>this * multiplicand</tt> */ public BigDecimal multiply(BigDecimal multiplicand) { long x = this.intCompact; long y = multiplicand.intCompact; int productScale = checkScale((long)scale+multiplicand.scale); // Might be able to do a more clever check incorporating the // inflated check into the overflow computation. if (x != INFLATED && y != INFLATED) { /* * If the product is not an overflowed value, continue * to use the compact representation. if either of x or y * is INFLATED, the product should also be regarded as * an overflow. See "Hacker's Delight" section 2-12 for * explanation of the overflow test. */ long product = x * y; if ( !(y != 0L && product/y != x) ) // not overflowed return BigDecimal.valueOf(product, productScale); } BigDecimal result = new BigDecimal(this.inflate().intVal.multiply(multiplicand.inflate().intVal), productScale); return result; } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this × * multiplicand)</tt>, with rounding according to the context settings. * * @param multiplicand value to be multiplied by this <tt>BigDecimal</tt>. * @param mc the context to use. * @return <tt>this * multiplicand</tt>, rounded as necessary. * @throws ArithmeticException if the result is inexact but the * rounding mode is <tt>UNNECESSARY</tt>. * @since 1.5 */ public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) { if (mc.precision == 0) return multiply(multiplicand); BigDecimal lhs = this; return lhs.inflate().multiply(multiplicand.inflate()).doRound(mc); } /** * Returns a <tt>BigDecimal</tt> whose value is <tt>(this / * divisor)</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. * * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method * should be used in preference to this legacy method. * * @param divisor value by which this <tt>BigDecimal</tt> is to be divided. * @param scale scale of the <tt>BigDecimal</tt> quotient to be returned. * @param roundingMode rounding mode to apply. * @return <tt>this / divisor</tt> * @throws ArithmeticException if <tt>divisor</tt> is zero, * <tt>roundingMode==ROUND_UNNECESSARY</tt> and * the specified scale is insufficient to represent the result * of the division exactly. * @throws IllegalArgumentException if <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 divisor, int scale, int roundingMode) { /* * IMPLEMENTATION NOTE: This method *must* return a new object * since dropDigits uses divide to generate a value whose * scale is then modified. */ if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -