BigDecimal中要注意的一些事

 

一、关于public BigDecimal(double val)

BigDecimal中三个主要的构造函数

1

public BigDecimal(double val)

将double表示形式转换为BigDecimal

不推荐

2

public BigDecimal(int val)

将int表示形式转换为BigDecimal

推荐

3

public BigDecimal(String val)

将字符串表示形式转换为BigDecimal

推荐

不推荐用 BigDecimal(double val)的原因是因为存在精度问题,如下图:

如果要探究造成这个问题的原因其实和BigDecimal没有关系;

原因:这其实和计算机使用二进制编码有关,在你使用BigDecimal(Double val)传入0.1时,这个0.1先被转换为Double,此时就已经出现了精度问题了,计算机只能用有限位数存储小数【二进制能用有限的位数表示的小数有:0.5、0.25、0.125 等】,所以存储的小数大多为一个近似值,十进制的 0.1 转为二进制,得到一个无限循环小数,所以传入到BigDecimal(Double val)中的数精度已经出现问题了,而BigDecimal又是为精确结果而设计的,所以bDouble就不是我们想要的0.1。

如何解决:

一、使用BigDecimal b1 = new BigDecimal("0.1");将数据转成String再使用BigDecimal(String val);

二、使用BigDecimal b1 = BigDecimal.valueOf(0.1);使用BigDecimal的valueOf()方法;

打开BigDecimal的valueOf()的源码

 

可以看到它也是直接转成String类型再调用BigDecimal(String val);方法

二、关于Non-terminating decimal expansion; no exact representable decimal result

Non-terminating decimal expansion; no exact representable decimal result.  翻译为:非终止十进制扩展; 没有确切的可表示的小数结果;

 

翻译为人话就是说:BigDecimal是为高精度计算而设计的,而你的值是没有精确结果的;

 

举例:

 

1.0/3.0是除不尽的,所以抛出异常

 

解决方案:使用BigDecimal.divide(BigDecimal divisor, int scale, RoundingMode roundingMode) ;

 

其中   scale  为保留的小数位;RoundingMode roundingMode 为取舍模式(如:RoundingMode.HALF_UP 四舍五入);

 

RoundingMode具有哪些模式请参照我的另一篇博客:https://www.cnblogs.com/minxl/p/10247770.html

 

 

posted @ 2019-01-14 16:24  36度  阅读(480)  评论(0编辑  收藏  举报