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即可,也可以根据自己业务需要选取,取整,进位取整……等。