当前位置:网站首页>BigDecimal除法的精度问题
BigDecimal除法的精度问题
2022-07-05 16:49:00 【全栈程序员站长】
大家好,又见面了,我是你们的朋友全栈君。
BigDecimal除法的精度问题
在使用BigDecimal的除法时,遇到一个鬼畜的问题,本以为的精度计算,结果使用返回0,当然最终发现还是自己的使用姿势不对导致的,因此记录一下,避免后面重蹈覆辙
I. 问题抛出
在使用BigDecimal做高精度的除法时,一不注意遇到了一个小问题,如下
@Test
public void testBigDecimal() {
BigDecimal origin = new BigDecimal(541253);
BigDecimal now = new BigDecimal(12389431);
BigDecimal val = origin.divide(now, RoundingMode.HALF_UP);
System.out.println(val);
origin = new BigDecimal(541253);
now = new BigDecimal(12389431.3);
val = origin.divide(now, RoundingMode.HALF_UP);
System.out.println(val);
origin = new BigDecimal(541253.4);
now = new BigDecimal(12389431);
val = origin.divide(now, RoundingMode.HALF_UP);
System.out.println(val);
}
复制代码
上面的输出是什么 ?
0
0
0.043686703610520937021487456961257
复制代码
为什么前面两个会是0呢,如果直接是 541253 / 12389431
= 0 倒是可以理解, 但是BigDecimal不是高精度的计算么,讲道理不应该不会出现这种整除的问题吧
我们知道在BigDecimal做触发时,可以指定保留小数的参数,如果加上这个,是否会不一样呢?
BigDecimal origin = new BigDecimal(541253);
BigDecimal now = new BigDecimal(12389431);
BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP);
System.out.println(val);
复制代码
输出结果为:
0.04369
复制代码
所以说在指定了保留小数之后,则没有问题,所以大胆的猜测一下,是不是上面的几种case中,由于scale值没有指定时,默认值不一样,从而导致最终结果的精度不同呢?
简单的深入源码分析一下,执行的方式为 origin.divide(now, RoundingMode.HALF_UP);
, 所以这个scale参数就瞄准origin对象,而这个对象,就只能去分析它的构造了,因为没有其他的地方使用
II. 源码定位
1. 整形传参构造
分析下面这一行, 直接进入源码
BigDecimal origin = new BigDecimal(541253);
复制代码
很明显的int传参构造,进去简单看一下
// java.math.BigDecimal#BigDecimal(int)
public BigDecimal(int val) {
this.intCompact = val;
this.scale = 0;
this.intVal = null;
}
public BigDecimal(long val) {
this.intCompact = val;
this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
this.scale = 0;
}
复制代码
so,很明确的知道默认的scale为0,也就是说当origin为正数时,以它进行的除法,不现实指定scale参数时,最终返回的都是没有小数的,同样看一眼,还有long的传参方式, BigInteger也一样
2. 浮点传参
接下来就是浮点的scale默认值确认了,这个构造相比前面的复杂一点,源码就不贴了,太长,也看不太懂做了些啥,直接用猥琐一点的方式,进入debug模式,单步执行
@Test
public void testBigDecimal() {
BigDecimal origin = new BigDecimal(541253.0);
BigDecimal now = new BigDecimal(12389431.1);
BigDecimal tmp = new BigDecimal(0.0);
}
复制代码
根据debug的结果,第一个,scale为0; 第二个scale为29, 第三个scale为0
3. String传参
依然是一大串的逻辑,同样采用单步debug的方式试下
@Test
public void testBigDecimal() {
BigDecimal origin = new BigDecimal("541253.0");
BigDecimal now = new BigDecimal("12389431.1");
BigDecimal t = new BigDecimal("0.0");
}
复制代码
上面三个的scale都是1
4. 小结
- 对于BigDecimal进行除法运算时,最好指定其scale参数,不然可能会有坑
- 对于BigDecimla的scale初始化的原理,有待深入看下BigDecimal是怎么实现的
II. 其他
1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明
尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/149837.html原文链接:https://javaforall.cn
边栏推荐
- easyNmon使用汇总
- The third lesson of EasyX learning
- CMake教程Step2(添加库)
- stirring! 2022 open atom global open source summit registration is hot!
- 【微信小程序】一文读懂小程序的生命周期和路由跳转
- Understand the usage of functions and methods in go language
- Is it safe to open a securities account by mobile phone? Detailed steps of how to buy stocks
- Precision epidemic prevention has a "sharp weapon" | smart core helps digital sentinels escort the resumption of the city
- The second day of learning C language for Asian people
- Application of threshold homomorphic encryption in privacy Computing: Interpretation
猜你喜欢
一文了解MySQL事务隔离级别
【剑指 Offer】63. 股票的最大利润
stirring! 2022 open atom global open source summit registration is hot!
Practical example of propeller easydl: automatic scratch recognition of industrial parts
What are the precautions for MySQL group by
MySql 查询符合条件的最新数据行
阈值同态加密在隐私计算中的应用:解读
The second day of learning C language for Asian people
thinkphp模板的使用
一个满分的项目文档是如何书写的|得物技术
随机推荐
Embedded UC (UNIX System Advanced Programming) -2
About JSON parsing function JSON in MySQL_ EXTRACT
WR | 西湖大学鞠峰组揭示微塑料污染对人工湿地菌群与脱氮功能的影响
URP下Alpha从Gamma空间到Linner空间转换(二)——多Alpha贴图叠加
【剑指 Offer】66. 构建乘积数组
winedt常用快捷键 修改快捷键latex编译按钮
Understand the usage of functions and methods in go language
CMake教程Step3(添加库的使用要求)
The two ways of domestic chip industry chain go hand in hand. ASML really panicked and increased cooperation on a large scale
飞桨EasyDL实操范例:工业零件划痕自动识别
什么是ROM
域名解析,反向域名解析nbtstat
What else do you not know about new map()
【二叉树】根到叶路径上的不足节点
Application of threshold homomorphic encryption in privacy Computing: Interpretation
C language to get program running time
Embedded -arm (bare board development) -1
33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)
高数 | 旋转体体积计算方法汇总、二重积分计算旋转体体积
7.Scala类