BigDecimal使用过程中的问题记录

使用不当记录,不涉及原理性的分析。

使用BigDecimal进行小数乘除运算,出来的结果不及预期。

public static void test(){
        BigDecimal oneHundred = new BigDecimal(100);
        BigDecimal percent = BigDecimal.valueOf(15.00);
        BigDecimal num1 = new BigDecimal(36.90).setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //num1:36.90
        System.out.println("num1:"+num1);
        BigDecimal c1 = new BigDecimal(0.01).setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //c1:0.01
        System.out.println("c1:"+c1);
        BigDecimal result1 = num1
                .multiply(oneHundred.subtract(percent))
                .multiply(c1);
        //result1:31.36500
        System.out.println("result1:"+result1);
        result1=result1.setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //result1:31.36
        System.out.println("result1:"+result1);

        System.out.println("----------------------------- ");
        BigDecimal num2 = new BigDecimal(36.90).setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //num2:36.90
        System.out.println("num2:"+num2);
        BigDecimal c2 = new BigDecimal(0.01);
        //c2:0.01000000000000000020816681711721685132943093776702880859375
        System.out.println("c2:"+c2);
        BigDecimal result2 = num2
                .multiply(oneHundred.subtract(percent));
        //result2:3136.500
        System.out.println("result2:"+result2);
        result2=result2.multiply(c2);
        //result2:31.36500000000000065291522188815065419476013630628585815429687500
        System.out.println("result2:"+result2);
        result2=result2.setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //result2:31.37
        System.out.println("result2:"+result2);
    }

输出结果都写在注释上。

两次的代码区别在于对待0.01上,一个进行了精度控制,一个没有。

教训:对于小数一定要进行精度控制。

这里再复习下BigDecimal中精度控制的常量含义:

ROUND_CEILING

接近正无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;如果为负,则舍入行为与 ROUND_DOWN 相同。注意,此舍入模式始终不会减少计算值。

ROUND_DOWN

接近零的舍入模式。在丢弃某部分之前始终不增加数字(即截短)。注意,此舍入模式始终不会增加计算值的大小。

ROUND_FLOOR

接近负无穷大的舍入模式。如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;如果为负,则舍入行为与 ROUND_UP 相同。注意,此舍入模式始终不会增加计算值。

ROUND_HALF_DOWN

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。

36.36500000000000065-->36.37

36.3650-->36.36

BigDecimal num = new BigDecimal(36.365000).setScale(4, BigDecimal.ROUND_HALF_DOWN);
System.out.println(num);
System.out.println(num.setScale(2, BigDecimal.ROUND_HALF_DOWN));

ROUND_HALF_EVEN

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。

ROUND_HALF_UP

向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。注意,这是我们大多数人在小学时就学过的舍入模式。

ROUND_UNNECESSARY

断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出 ArithmeticException。

ROUND_UP

舍入远离零的舍入模式。在丢弃非零部分之前始终增加数字。注意,此舍入模式始终不会减少计算值的大小。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值