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

  • Post author:
  • Post category:java


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


1.BigDecimal的构造方法

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

我们今天主要说一下


BigDecimal对象中构造方法传入double与String的区别


。我们来通过一些代码来看一下两者的实际效果

1)BigDecimal(double val)

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

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

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

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



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



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



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

所以,综上我们可以得出一个结论,即:


当BigDecimal构造方法对象为double时,会出现精度的损失。



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

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

2)BigDecimal(String val)

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

很神奇,当


传入的是String时,并未出现精度的损失


,amazing

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

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

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



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)



版权声明:本文为weixin_42386014原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。