Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案

当我们在开发的时候,有时候根据需求来讲,会要求小数点后精确到几位数,例如涉及到费用的问题,通常会让我们精确到小数点后4位,就类似于“0.3333”的格式,当我们在想要进行精确到小数点后几位时,这时候就会想到BigDeimal对象来进行转化,不过在进行转化的过程中,笔者遇见了几个不小的“坑”。

1.BigDecimal的构造方法

我们来看看JDK1.8中对BigDecimal对象是如何解释他的构造方法的吧。

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第1张图片

我们今天主要说一下BigDecimal对象中构造方法传入double与String的区别。我们来通过一些代码来看一下两者的实际效果

1)BigDecimal(double val) 

当我们想要保留小数点后四位小数,构造方法为double时,会出现什么情况呢?

     当我们直接定义一个double数据a,通过BigDecimal对象进行转换时,发现并没有精度的损失,

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第2张图片

但是,当我们设置另外一个double数据b时,两个double数据做除运算,我们来看一看发生了什么

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第3张图片

我们会发现,当我们直接打印出 a / b 时,此时未做转换,c 为 0.85;但是当我们把 a / b 的结果放入构造方法中时(即把0.85放入构造方法中),会发现,最后通过BigDecimal对象转化出的double数据为0.8499;

所以我们可以得出一个结论,当BigDecimal构造方法对象为double时,会出现精度的损失。

这时候可能会有人说,你构造方法中传入的是 “a / b”,那是否是a/b运算出现的精度损失,而并非是构造方法中直接传入的double出现的精度损失?

首先,第一点,double型数据做运算得出的结果同样也是double型数据,第二点,我们来看看系统的运算结果:

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第4张图片

所以,综上我们可以得出一个结论,即:当BigDecimal构造方法对象为double时,会出现精度的损失。

 

彩蛋:我们没限制BigDecimal的位数的时候,它的值是多少呢?

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第5张图片

这时候我不得不怀疑,double本身可能就是个有问题的数据呀【滑稽】

 

2)BigDecimal(String val)

我们同样做一个实验,把步骤1中传入的double数据改为String类型时,会发现这样一个有趣的现象。

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第6张图片

很神奇,当传入的是String时,并未出现精度的损失,amazing

所以!我大胆瞎猜!double是基本数据类型!有位数限制!可能内部早就做了四舍五入的处理!String没有位数限制!所以没有精度损失![这句话我瞎说的]

 

还有一个地方需要大家注意,当在做double数据除运算的时候,中间转为String可以,但是还有一个方法,就是把doule都转为BigDecimal对象,然后再做除运算;

 

注意圈出的部分,如果不设置这一步,并且是有无限循环时,就会报错:

Java中BigDecimal对象与double之间转换涉及的精度问题及“no exact representable decimal result.”解决方案_第7张图片

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    at java.math.BigDecimal.divide(BigDecimal.java:1690)
    at TestProject.main(TestProject.java:18)

 

 

你可能感兴趣的:(Java编程)