java关于BigDecimal使用小总结

原创
2020/11/27 16:49
阅读数 1.5K

1、做除法运算时可能出现的错误;
2、加减乘除按什么顺序执行;

测试代码1、

    @Test
    public void testDemical(){
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);
        BigDecimal c = new BigDecimal(5);
        BigDecimal result_1 = b.divide(a);
        log.info("result_1的结果为={}", result_1.toString());
    }

输出结果

16:29:26.455 [main] INFO test.TestShop - result_1的结果为=1.5

很正常,毕竟3除以2等于1.5.口算都出来了。

看下面测试2、

@Test
    public void testDemical(){
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);
        BigDecimal c = new BigDecimal(5);
        BigDecimal result_1 = a.divide(b);
        log.info("result_1的结果为={}", result_1.toString());
    }

输出结果是0.6666……吗? 不是的额。。

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

	at java.math.BigDecimal.divide(BigDecimal.java:1693)
	at test.TestShop.testDemical(TestShop.java:120)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

报错了,报错原因是因为除不尽,而且没指定商的保留小数位数,只好报错。 解决代码如下:
测试3

   @Test
    public void testDemical(){
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);
        BigDecimal c = new BigDecimal(5);
        BigDecimal result_1 = a.divide(b, 4, RoundingMode.HALF_UP);
        log.info("result_1的结果为={}", result_1.toString());

    }
	
	输出结果  
	16:34:03.915 [main] INFO test.TestShop - result_1的结果为=0.6667  

很正常。
为什么要记录这个呢,因为在实际开发过程中常常会因为开发时没出现异常,因为会下意识的拿一些简单的1/2/3等数据做测试,除尽的情况下不会报错。代码发到测试或线上,测试一测或客户一用就bug了。因此要切记,Bigdemical 类型做高精度运算做除法运算时一定要指定保留小数位数,否则就是坑。

第二个问题

测试代码4

 @Test
    public void testDemical(){
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);
        BigDecimal c = new BigDecimal(5);
        BigDecimal result_1 = a.add(b).multiply(c);
        log.info("result_1的结果为={}", result_1.toString());

    }

请猜以上代码输出啥? 当有加减乘除同时运算时会按乘除>加减优先级然后按从左到右的顺序执行么?
结果如下:

16:40:42.283 [main] INFO test.TestShop - result_1的结果为=25

从结果看出来是按从左到右的顺序计算的,和乘除加减无关。此时要注意当计算有顺序是一定要加上括号。

   @Test
    public void testDemical(){
        BigDecimal a = new BigDecimal(2);
        BigDecimal b = new BigDecimal(3);
        BigDecimal c = new BigDecimal(5);
        BigDecimal result_1 = a.add( b.multiply(c) );
        log.info("result_1的结果为={}", result_1.toString());

    }

结果为:  
16:46:13.748 [main] INFO test.TestShop - result_1的结果为=17


保留小数时有很多模式,一般取RoundingMode.HALF_UP即可,也可以根据自己业务需要选取,取整,进位取整……等。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
1 收藏
0
分享
返回顶部
顶部