java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal res

来源:互联网 发布:mac word转pdf错误 编辑:程序博客网 时间:2024/05/23 20:09

使用BigDecimal进行出发运算(调用divide())时出现的,是因为不整除产生无先循环小数所致。源码如下:

 public BigDecimal divide(BigDecimal divisor) {        BigInteger p = this.getUnscaledValue();        BigInteger q = divisor.getUnscaledValue();        BigInteger gcd; // greatest common divisor between 'p' and 'q'        BigInteger quotAndRem[];        long diffScale = (long)scale - divisor.scale;        int newScale; // the new scale for final quotient        int k; // number of factors "2" in 'q'        int l = 0; // number of factors "5" in 'q'        int i = 1;        int lastPow = FIVE_POW.length - 1;        if (divisor.isZero()) {            throw new ArithmeticException("Division by zero");        }        if (p.signum() == 0) {            return zeroScaledBy(diffScale);        }        // To divide both by the GCD        gcd = p.gcd(q);        p = p.divide(gcd);        q = q.divide(gcd);        // To simplify all "2" factors of q, dividing by 2^k        k = q.getLowestSetBit();        q = q.shiftRight(k);        // To simplify all "5" factors of q, dividing by 5^l        do {            quotAndRem = q.divideAndRemainder(FIVE_POW[i]);            if (quotAndRem[1].signum() == 0) {                l += i;                if (i < lastPow) {                    i++;                }                q = quotAndRem[0];            } else {                if (i == 1) {                    break;                }                i = 1;            }        } while (true);        // If  abs(q) != 1  then the quotient is periodic        if (!q.abs().equals(BigInteger.ONE)) {        //异常信息            throw new ArithmeticException("Non-terminating decimal expansion; no exact representable decimal result");        }        // The sign of the is fixed and the quotient will be saved in 'p'        if (q.signum() < 0) {            p = p.negate();        }        // Checking if the new scale is out of range        newScale = safeLongToInt(diffScale + Math.max(k, l));        // k >= 0  and  l >= 0  implies that  k - l  is in the 32-bit range        i = k - l;        p = (i > 0) ? Multiplication.multiplyByFivePow(p, i)        : p.shiftLeft(-i);        return new BigDecimal(p, newScale);    }

解决方案:

使用三参数除法函数divide(),指定小数精确度。如:

new BigDecimal(mGypsumCountSum).divide(new BigDecimal(count),8,BigDecimal.ROUND_HALF_UP)

此处divide()的第二个参数是8表示小数精确8位。

阅读全文
0 0
原创粉丝点击