⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floatmul.java

📁 浮点数加减乘除
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
         * Rescale dividend or divisor (whichever can be "upscaled" to         * produce correctly scaled quotient).         * Take care to detect out-of-range scales         */        BigDecimal dividend;        if (checkScale((long)scale + divisor.scale) >= this.scale) {            dividend = this.setScale(scale + divisor.scale);        } else {            dividend = this;            divisor = divisor.setScale(checkScale((long)this.scale - scale));        }		boolean compact = dividend.intCompact != INFLATED && divisor.intCompact != INFLATED;	long div = INFLATED;	long rem = INFLATED;;	BigInteger q=null, r=null;	if (compact) {	    div = dividend.intCompact / divisor.intCompact;	    rem = dividend.intCompact % divisor.intCompact;	} else {	    // Do the division and return result if it's exact.	    BigInteger i[] = dividend.inflate().intVal.divideAndRemainder(divisor.inflate().intVal);	    q = i[0];	    r = i[1];	}	// Check for exact result	if (compact) {	    if (rem == 0)		return new BigDecimal(div, scale);	} else {	    if (r.signum() == 0)		return new BigDecimal(q, scale);	}	        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;	    if (compact) {		 cmpFracHalf = longCompareTo(Math.abs(2*rem), Math.abs(divisor.intCompact));	    } else {		// add(r) here is faster than multiply(2) or shiftLeft(1)		cmpFracHalf= r.add(r).abs().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		    if (compact) 			increment = (div & 1L) != 0L;		    else			increment = q.testBit(0);   // true iff q is odd		}            }	}	if (compact) {	    if (increment)		div += signum; // guaranteed not to overflow	    return new BigDecimal(div, scale);	} else {	    return (increment		    ? new BigDecimal(q.add(BigInteger.valueOf(signum)), scale)		    : new BigDecimal(q, scale));	}    }    /**     * 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.     *      * @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==RoundingMode.UNNECESSARY</tt> and     *         the specified scale is insufficient to represent the result     *         of the division exactly.     * @since 1.5     */    public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {	return divide(divisor, scale, roundingMode.oldMode);    }    /**     * Returns a <tt>BigDecimal</tt> whose value is <tt>(this /     * divisor)</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.     *      * <p>The new {@link #divide(BigDecimal, 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  roundingMode rounding mode to apply.     * @return <tt>this / divisor</tt>     * @throws ArithmeticException if <tt>divisor==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 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 roundingMode) {            return this.divide(divisor, scale, roundingMode);    }    /**     * Returns a <tt>BigDecimal</tt> whose value is <tt>(this /     * divisor)</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  divisor value by which this <tt>BigDecimal</tt> is to be divided.     * @param  roundingMode rounding mode to apply.     * @return <tt>this / divisor</tt>     * @throws ArithmeticException if <tt>divisor==0</tt>, or     *         <tt>roundingMode==RoundingMode.UNNECESSARY</tt> and     *         <tt>this.scale()</tt> is insufficient to represent the result     *         of the division exactly.     * @since 1.5     */    public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {	return this.divide(divisor, scale, roundingMode.oldMode);    }    /**     * Returns a <tt>BigDecimal</tt> whose value is <tt>(this /     * divisor)</tt>, and whose preferred scale is <tt>(this.scale() -     * divisor.scale())</tt>; if the exact quotient cannot be     * represented (because it has a non-terminating decimal     * expansion) an <tt>ArithmeticException</tt> is thrown.     *     * @param  divisor value by which this <tt>BigDecimal</tt> is to be divided.     * @throws ArithmeticException if the exact quotient does not have a     *         terminating decimal expansion     * @return <tt>this / divisor</tt>     * @since 1.5     * @author Joseph D. Darcy     */    public BigDecimal divide(BigDecimal divisor) {	/*	 * Handle zero cases first.	 */        if (divisor.signum() == 0) {   // x/0            if (this.signum() == 0)    // 0/0                throw new ArithmeticException("Division undefined");  // NaN            throw new ArithmeticException("Division by zero");	}	// Calculate preferred scale	int preferredScale = (int)Math.max(Math.min((long)this.scale() - divisor.scale(),						    Integer.MAX_VALUE), Integer.MIN_VALUE);        if (this.signum() == 0)        // 0/y            return new BigDecimal(0, preferredScale);	else {	    this.inflate();	    divisor.inflate();	    /*	     * If the quotient this/divisor has a terminating decimal	     * expansion, the expansion can have no more than	     * (a.precision() + ceil(10*b.precision)/3) digits.	     * Therefore, create a MathContext object with this	     * precision and do a divide with the UNNECESSARY rounding	     * mode.	     */	    MathContext mc = new MathContext( (int)Math.min(this.precision() + 							    (long)Math.ceil(10.0*divisor.precision()/3.0),							    Integer.MAX_VALUE),					      RoundingMode.UNNECESSARY);	    BigDecimal quotient;	    try {		quotient = this.divide(divisor, mc);	    } catch (ArithmeticException e) {		throw new ArithmeticException("Non-terminating decimal expansion; " + 					      "no exact representable decimal result.");	    }	    int quotientScale = quotient.scale();	    // divide(BigDecimal, mc) tries to adjust the quotient to	    // the desired one by removing trailing zeros; since the	    // exact divide method does not have an explicit digit	    // limit, we can add zeros too.	    	    if (preferredScale > quotientScale)		return quotient.setScale(preferredScale);	    return quotient;	}    }    /**     * Returns a <tt>BigDecimal</tt> whose value is <tt>(this /     * divisor)</tt>, with rounding according to the context settings.     *     * @param  divisor value by which this <tt>BigDecimal</tt> is to be divided.     * @param  mc the context to use.     * @return <tt>this / divisor</tt>, rounded as necessary.     * @throws ArithmeticException if the result is inexact but the     *         rounding mode is <tt>UNNECESSARY</tt> or      *         <tt>mc.precision == 0</tt> and the quotient has a      *         non-terminating decimal expansion.     * @since  1.5     */    public BigDecimal divide(BigDecimal divisor, MathContext mc) {        if (mc.precision == 0)            return divide(divisor);        BigDecimal lhs = this.inflate();     // left-hand-side        BigDecimal rhs = divisor.inflate();  // right-hand-side        BigDecimal result;                   // work	long preferredScale = (long)lhs.scale() - rhs.scale();        // Now calculate the answer.  We use the existing        // divide-and-round method, but as this rounds to scale we have        // to normalize the values here to achieve the desired result.        // For x/y we first handle y=0 and x=0, and then normalize x and        // y to give x' and y' with the following constraints:        //   (a) 0.1 <= x' < 1        //   (b)  x' <= y' < 10*x'        // Dividing x'/y' with the required scale set to mc.precision then        // will give a result in the range 0.1 to 1 rounded to exactly        // the right number of digits (except in the case of a result of        // 1.000... which can arise when x=y, or when rounding overflows        // The 1.000... case will reduce properly to 1.        if (rhs.signum() == 0) {      // x/0            if (lhs.signum() == 0)    // 0/0                throw new ArithmeticException("Division undefined");  // NaN            throw new ArithmeticException("Division by zero");	}        if (lhs.signum() == 0)        // 0/y            return new BigDecimal(BigInteger.ZERO, 				  (int)Math.max(Math.min(preferredScale,							 Integer.MAX_VALUE),						Integer.MIN_VALUE));        BigDecimal xprime = new BigDecimal(lhs.intVal.abs(), lhs.precision());        BigDecimal yprime = new BigDecimal(rhs.intVal.abs(), rhs.precision());        // xprime and yprime are now both in range 0.1 through 0.999...	if (mc.roundingMode == RoundingMode.CEILING || 	    mc.roundingMode == RoundingMode.FLOOR) {	    // The floor (round toward negative infinity) and ceil	    // (round toward positive infinity) rounding modes are not	    // invariant under a sign flip.  If xprime/yprime has a	    // different sign than lhs/rhs, the rounding mode must be	    // changed.	    if ((xprime.signum() != lhs.signum()) ^		(yprime.signum() != rhs.signum())) {		mc = new MathContext(mc.precision, 				     (mc.roundingMode==RoundingMode.CEILING)?				     RoundingMode.FLOOR:RoundingMode.CEILING);	    }	}        if (xprime.compareTo(yprime) > 0)    // satisfy constraint (b)          yprime.scale -= 1;                 // [that is, yprime *= 10]        result = xprime.divide(yprime, mc.precision, mc.roundingMode.oldMode);        // correct the scale of the result...        result.scale = checkScale((long)yprime.scale - xprime.scale            - (rhs.scale - lhs.scale) + mc.precision);        // apply the sign        if (lhs.signum() != rhs.signum())            result = result.negate();        // doRound, here, only affects 1000000000 case.        result = result.doRound(mc);	    	if (result.multiply(divisor).compareTo(this) == 0) {	    // Apply preferred scale rules for exact quotients	    return result.stripZerosToMatchScale(preferredScale);	}	else {	    return result;	}    }    /**     * Returns a <tt>BigDecimal</tt> whose value is the integer part     * of the quotient <tt>(this / divisor)</tt> rounded down.  The     * preferred scale of the result is <code>(this.scale() -     * divisor.scale())</code>.     *     * @param  divisor value by which this <tt>BigDecimal</tt> is to be divided.     * @return The integer part of <tt>this / divisor</tt>.     * @throws ArithmeticException if <tt>divisor==0</tt>     * @since  1.5     */    public BigDecimal divideToIntegralValue(BigDecimal divisor) {	// Calculate preferred scale	int preferredScale = (int)Math.max(Math.min((long)this.scale() - divisor.scale(),						    Integer.MAX_VALUE), Integer.MIN_VALUE);	this.inflate();	divisor.inflate();        if (this.abs().compareTo(divisor.ab

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -