double、Double与BigDecimal

在电商与金融场景中,对数据的敏感程度较高,一旦出现了精度的问题,如果涉及到金钱,精度问题造成了误差,误差就会演变成错误,会造成一定的经济损失,这是大家都不希望见到的

所以今天,来学习一下,如何正确的使用double、Double与BigDecimal


double与Doubl
e

double是一种基本数据类型,创建引用,存放在栈中,8字节
,不可为NULL

Double是一个类,创建对象,存放在堆中,可以为NULL

Double是对double类型的封装(也可以说是包装类),内置很多方法可以实现String到double的转换,以及获取各种double类型的属性值(MAX_VALUE,SIZE等)

double可以自动拆箱和自动装箱,把double类型数据转换成Double,那么这个数据就可以使用Double中的所有方法

另外,由于Double是包装类型(可为NULL),在接口中使用的时候,也只能使用包装类型,不能使用基本数据类型,例如:ThreadLocal< Double
>、List< Double
>、Map< Double
,Object>等

double在使用中,还会有一些隐藏的坑

1.计算时出现不准确的问题

System.out.println(12.3 + 45.6);
// 57.900000000000006
System.out.println(1.14 / 100);
// 0.011399999999999999

double的小数部分容易出现使用二进制无法准确表示

如十进制的0.1,0.2,0.3,0.4 都不能准确表示成二进制


可参考: https://blog.csdn.net/Lixuanshengchao/article/details/82049191

2.判断double是否相等需要注意

在使用 == 判断两个double是否相等时,如果double超过了16位,会出现问题

16位,不相等

double a = 1.1234567890123451;
double b = 1.1234567890123452;
System.out.println(a == b); // false

17位,相等

double a = 1.12345678901234561;
double b = 1.12345678901234567;
System.out.println(a == b); // true

如果在使用场景中,对数据的敏感程度不高,可以容忍精度损失的情况,例如:计算占比,百分比等情况,本身对数据的结果是未知的,且数据不敏感, 推荐使用double,节省了时间空间

Double与BigDecimal

与Double相同,BigDecimal也是一个类, 创建对象,存放在堆中

上文我们说过,double超过了16位就会有一些精度损失的问题,那么BigDecimal就是用来对超过16位有效位的数进行精确的运算

因为BigDecimal是一个类,所以在运算中无法直接进行 + – x &divide; 等算术运算符的的操作,而要调用对应的方法

同样在BigDecimal在使用中也要注意一些问题

1.new BigDecimal(double) 与  BigDecimal.valueOf(double)

先来举个例子

BigDecimal bd1 = BigDecimal.valueOf(12.3);
// 12.3
BigDecimal bd2 = new BigDecimal(12.3);
// 12.300000000000000710542735760100185871124267578125

通过上面的例子可以看出,new BigDecimal的方式,可能不是你想要的结果,这种问题,早在
源码中 
BigDecimal(double) 构造函数的注释中就有说明(感兴趣的请查看源码),说明如下:

1)参数类型为double的构造方法的结果有一定的不可预知性

有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于

0.1000000000000000055511151231257827021181583404541015625,这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)

这样,传入到构造方法的值不会正好等于 
0.1(虽然表面上等于该值)

2)String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1,因此,比较而言, 通常 建议优先使用String构造方法

3)当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要

获取该结果,请使用 static valueOf(double)
方法



另外,BigDecimal.valueOf() 是静态工厂类,永远优先于构造函数,


所以,在使用的时候,
推荐使用
BigDecimal.valueOf(xxx)

dd

原文 

http://www.louisvv.com/archives/2514.html

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » double、Double与BigDecimal

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址