BigDecimal的一些用法

    在多功能计算器项目中,计算器和单位换算功能都要求要有20位的精确度,并且要支持超大数,因此double类型就完全不够看了(double类型最多支持16位有效数字,且最大值只支持10^308次方),最后确定使用BigDecimal承载数据进行运算。下面我就列出一些BigDecimal的一些常用用法及注意点:

    BigDecimal的常用方法:

     加:add(BigDecima)

     减:subtract(BigDecimal)

     乘:multiply(BigDecimal)

     除:divide(BigDecimal)

     乘方:pow(int)

     取绝对值:abs()

     取反:negate()

     对比:compareTo(BigDecimal)

     设置小数点精确度:setScale(int)

     设置保留小数点精确度并添加保留方式(直接加1或者四舍五入):setScale(int, int)

     

    BigDecimal支持任意精度,任意长度的浮点数运算,但在运算的时候最好设置各个操作数的小数精确度,特别是除法。结果需要保留几位小数,如果没有设置除法的操作数的小数精确度,计算结果的精确度就会和操作数中最低精确度一致,导致计算结果不正确,如下例子:

            String a = "1";
            String b = "4.56";
            BigDecimal aBD = new BigDecimal(a);
            BigDecimal bBD = new BigDecimal(b);
            BigDecimal resultBD = aBD.divide(bBD).setScale(3, java.math.BigDecimal.ROUND_HALF_UP);

    3是保留小数,ROUND_HALF_UP是四舍五入,此参数的其他值请查看文章:

http://www.bdqn.cn/news/201311/11834.shtml

    这个例子你期望的是0.219,但是你实际会得到0。为什么呢?这就是保留精确度问题了,a是一个整数,运算时把结果当作整数取了,那就是0了。所以,应该按下面的运算:

            String a = "1";
            String b = "4.56";
            BigDecimal aBD = new BigDecimal(a).setScale(3);
            BigDecimal bBD = new BigDecimal(b).setScale(3);
            BigDecimal resultBD = aBD.divide(bBD).setScale(3, java.math.BigDecimal.ROUND_HALF_UP);

    这样,你就会得到一个正确的值了。

    还有一个需要注意的点,计算结果,如例子中的resultBD一定要设置其setScale的第二个参数,不然会报错。如果计算结果没有按某个方式进行截断,那么机器就不知道如何去取这个结果了,因此报错。

 

BigDecimal的结果格式化:

将BigDecimal计算的结果toString()输出,不是按科学计数法的格式的,如果想改成这种格式,可以使用DecimalFormat进行转换,具体如下:

    private static final String EXPR_PATTERN = "0.##########E0";
    private static final String PATTERN = "0.##########";
    private static final String INTEGER_MIN_VALUE_CHANGE_TO_EXPR = "10000000";
    private static final String DECIMAL_MIN_VALUE_CHANGE_TO_EXPR = "0.0001";
    /**
     * Tpv loy.ouyang: jude number is able to convert to expr display
     */
private static boolean numberStringCanConvertToExpr(BigDecimal bd) {
        if (bd == null) {
            return false;
        }
        boolean result = false;
        BigDecimal absDB = bd.abs();
        if ((absDB.compareTo(new BigDecimal(DECIMAL_MIN_VALUE_CHANGE_TO_EXPR)) <= 0) ||
                (absDB.compareTo(new BigDecimal(INTEGER_MIN_VALUE_CHANGE_TO_EXPR)) >= 0)) {
            result = true;
        }

        if (absDB.compareTo(new BigDecimal(0)) == 0) {
            result = false;
        }
        return result;
    }

    /**
     * Tpv loy.ouyang: format string to expr to display
     */
    public static String formatStringToExpr(BigDecimal bd) {
        if (bd == null) {
            return null;
        }
        DecimalFormat df = new DecimalFormat();
        if (numberStringCanConvertToExpr(bd)) {
            df.applyPattern(EXPR_PATTERN);
        } else {
            df.applyPattern(PATTERN);
        }
        return df.format(bd);
    }

定义了超大数和超小数的显示PATTERN,0.##########代表最多显示10位小数,并判定绝对值多大的数和绝对值多小的数需要转化位科学记数法,最后用DecimalFormat就可以搞定了。

 

 参考文章:

http://www.bdqn.cn/news/201311/11834.shtml

   

  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值