bigdecimal js 判断等于0_为啥阿里禁用BigDecimal的equals方法做等值比较

e73e62958815144aa522bd99cb3d0a39.png

BigDecimal,相信对于很多人来说都不陌生,很多人都知道它的用法,这是一种java.math包中提供的一种可以用来进行精确运算的类型。

很多人都知道,在进行金额表示、金额计算等场景,不能使用double、float等类型,而是要使用对精度支持的更好的BigDecimal。

所以,很多支付、电商、金融等业务中,BigDecimal的使用非常频繁。而且不得不说这是一个非常好用的类,其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。

除了需要用BigDecimal表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。

关于BigDecimal等值判断的这个知识点,在最新版的《阿里巴巴Java开发手册》中也有说明:

193b23d72f508db12ebc9af7be87feea.png

那么,为什么会有这样的要求呢?背后的思考是什么呢?

其实,我在之前的CodeReview中,看到过以下这样的低级错误:

if(bigDecimal == bigDecimal1){// 两个数相等
}

这种错误,相信聪明的读者一眼就可以看出问题,因为BigDecimal是对象,所以不能用==来判断两个数字的值是否相等。

以上这种问题,在有一定的经验之后,还是可以避免的,但是聪明的读者,看一下以下这行代码,你觉得他有问题吗:

if(bigDecimal.equals(bigDecimal1)){// 两个数相等
}

可以明确的告诉大家,以上这种写法,可能得到的结果和你预想的不一样!

先来做个实验,运行以下代码:

BigDecimal bigDecimal = new BigDecimal(1);
BigDecimal bigDecimal1 = new BigDecimal(1);
System.out.println(bigDecimal.equals(bigDecimal1));
BigDecimal bigDecimal2 = new BigDecimal(1);
BigDecimal bigDecimal3 = new BigDecimal(1.0);
System.out.println(bigDecimal2.equals(bigDecimal3));
BigDecimal bigDecimal4 = new BigDecimal("1");
BigDecimal bigDecimal5 = new BigDecimal("1.0");
System.out.println(bigDecimal4.equals(bigDecimal5));

以上代码,输出结果为:

true
truefalse

BigDecimal的equals原理

通过以上代码示例,我们发现,在使用BigDecimal的equals方法对1和1.0进行比较的时候,有的时候是true(当使用int、double定义BigDecimal时),有的时候是false(当使用String定义BigDecimal时)。

那么,为什么会出现这样的情况呢,我们先来看下BigDecimal的equals方法。

在BigDecimal的JavaDoc中其实已经解释了其中原因:

Compares this  BigDecimal with the specified Object for equality.  Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by  this method)

大概意思就是,equals方法和compareTo并不一样,equals方法会比较两部分内容,分别是值(value)和精度(scale)

对应的代码如下:

09cc57ce4c68b01ea66690f4754bd815.png

所以,我们以上代码定义出来的两个BigDecimal对象(bigDecimal4和bigDecimal5)的精度是不一样的,所以使用equals比较的结果就是false了。

尝试着对代码进行debug,在debug的过程中我们也可以看到bigDecimal4的精度是0,而bigDecimal5的精度是1。

dd0b4b881b68ec0ea64a22ff01fdf191.png

到这里,我们大概解释清楚了,之所以equals比较bigDecimal4和bigDecimal5的结果是false,是因为精度不同。

那么,为什么精度不同呢?为什么bigDecimal2和bigDecimal3的精度是一样的(当使用int、double定义BigDecimal时),而bigDecimal4和bigDecimal5却不一样(当使用String定义BigDecimal时)呢?

为什么精度不同

这个就涉及到BigDecimal的精度问题了,这个问题其实是比较复杂的,由于不是本文的重点,这里面就简单介绍一下吧。大家感兴趣的话,后面单独讲。

首先,BigDecimal一共有以下4个构造方法:

BigDecimal(int)
BigDecimal(double) 
BigDecimal(long) 
BigDecimal(String)

以上四个方法,创建出来的的BigDecimal的精度是不同的。

BigDecimal(long) 和BigDecimal(int)

首先,最简单的就是BigDecimal(long) 和BigDecimal(int),因为是整数,所以精度就是0

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;
}

BigDecimal(double)

而对于BigDecimal(double) ,当我们使用new BigDecimal(0.1)创建一个BigDecimal 的时候,其实创建出来的值并不是正好等于0.1的,而是0.1000000000000000055511151231257827021181583404541015625 。这是因为doule自身表示的只是一个近似值。

那么,无论我们使用new BigDecimal(0.1)还是new BigDecimal(0.10)定义,他的近似值都是0.1000000000000000055511151231257827021181583404541015625这个,那么他的精度就是这个数字的位数,即55。

440843df2dd8d965e228a41e3cc4f0ea.png

其他的浮点数也同样的道理。对于new BigDecimal(1.0)这样的形式来说,因为他本质上也是个整数,所以他创建出来的数字的精度就是0。

所以,因为BigDecimal(1.0)和BigDecimal(1.00)的精度是一样的,所以在使用equals方法比较的时候,得到的结果就是true。

BigDecimal(string)

而对于BigDecimal(double) ,当我们使用new BigDecimal("0.1")创建一个BigDecimal 的时候,其实创建出来的值正好就是等于0.1的。那么他的精度也就是1。

如果使用new BigDecimal("0.10000"),那么创建出来的数就是0.10000,精度也就是5。

所以,因为BigDecimal("1.0")和BigDecimal("1.00")的精度不一样,所以在使用equals方法比较的时候,得到的结果就是false。

如何比较BigDecimal

前面,我们解释了BigDecimal的equals方法,其实不只是会比较数字的值,还会对其精度进行比较。

所以,当我们使用equals方法判断判断两个数是否相等的时候,是极其严格的。

那么,如果我们只想判断两个BigDecimal的值是否相等,那么该如何判断呢?

BigDecimal中提供了compareTo方法,这个方法就可以只比较两个数字的值,如果两个数相等,则返回0。

    BigDecimal bigDecimal4 = new BigDecimal("1");BigDecimal bigDecimal5 = new BigDecimal("1.0000");System.out.println(bigDecimal4.compareTo(bigDecimal5));

以上代码,输出结果:

0

其源码如下:

a36129f6f5c20c17eaef6f91c93dc4e4.png

总结

BigDecimal是一个非常好用的表示高精度数字的类,其中提供了很多丰富的方法。

但是,他的equals方法使用的时候需要谨慎,因为他在比较的时候,不仅比较两个数字的值,还会比较他们的精度,只要这两个因素有一个是不相等的,那么结果也是false、

如果读者想要对两个BigDecimal的数值进行比较的话,可以使用compareTo方法。

地址:https://www.toutiao.com/i6874812439561503243/
作者:java互联网架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git提交到github总是要输入密码_GitHub不为人知的秘密

本来想叫《GitHub骚操作》的,发现相关的文章已经有很多,而且和我本章要讲的内容完全不同,所以就换了这个也算贴切的标题。起因之前写过一篇文章《VM Manager 插件分享》,事后我发现有个地方不对劲!看之前文章标题大家应…

MyBatis中大于号以及小于号的表达方式

mybatis使用的是xml格式的文件。使用>和<号的时候&#xff0c;会存在与xml的标签的规范冲突。 1.场景还原 在实际项目中&#xff0c;有很多需求需要通过设定一个具体的时间段来搜索或过滤所需的数据&#xff0c;今天笔者就mybatis中时间比较涉及到的大于&#xff0c;小于…

ug冲模标准件库_昆山兴模lt;携手gt;武汉益模,打通冲模“智能设计+精益管理”的最后一道关卡...

武汉益模科技股份有限公司是国内领先的工业互联网及智能制造的解决方案提供商&#xff0c;为模具、装备、军工、汽车、家电及等有柔性化生产需求的工厂提供专业的智能设计/信息化管理/智能加工/数字化工厂等工业软件、工业机器人自动化以及智能装备&#xff0c;拥有麦格纳、安波…

简述网络调研的作用_利用龙伯球透镜天线提升高铁4G网络覆盖

透镜天线&#xff0c;一种能够通过电磁波&#xff0c;将点源或线源的球面波或柱面波转换为平面波从而获得笔形、扇形或其他形状波束的天线。通过合适设计透镜表面形状和折射率 n&#xff0c;调节电磁波的相速以获得辐射口径上的平面波前。透镜天线吸收了许多光信息工程技术&…

SQLIntegrityConstraintViolationException: 异常解决

SQLIntegrityConstraintViolationException: Duplicate entry ‘xxx’ for key yyyzzz’异常解决 一. 异常现象 在做Java Web项目操作数据库添加数据的时候&#xff0c;突然发现曝出如下图所示异常&#xff1a; Caused by: java.sql.SQLIntegrityConstraintViolationExceptio…

一步怎么测量图片_测量不容易?15套测量仪器实操手册+自动计算表格,自学也可以...

测量不容易&#xff1f;15套测量仪器实操手册自动计算表格&#xff0c;自学也可以很多施工羡慕测量工资高&#xff0c;但是测量工资高也就意味着责任大&#xff0c;施工在休息的时候测量就下工地了&#xff0c;施工聚会的时候&#xff0c;测量在埋头苦算。如果施工想要干测量该…

Java 中判断一个字符串是否包含另外一个字符串的方法

方法一&#xff1a;indexOf(String s) 可以配合indexOf(String s)的使用&#xff0c;如果包含&#xff0c;返回的值是包含该子字符串在父类字符串中起始位置&#xff1b;如果不包含必定全部返回值为-1 public void test02() {String str1"张三";String str2"是…

速看!销冠高效给客户群发消息的秘诀

你是不是也有过这样的疑问&#xff1a;明明都是给客户群发消息&#xff0c;为什么别人的成交率那么高&#xff0c;自己却效果一般呢&#xff1f; 今天就给大家分享销冠常用的高效群发消息秘诀&#xff0c;让大家都能更好地与客户进行沟通&#xff0c;提高成交率&#xff01; …

不显示_电脑不显示桌面图标怎么办?

在现在这个社会时代中&#xff0c;人们对电脑的使用频率非常的高&#xff0c;电脑可以说已经成为了大家在生活中不可或缺的必备品。但是在使用电脑过程中的时候也都容易出现故障。那么&#xff0c;若碰上 电脑开机后只显示桌面的背景而没有任何程序和应用的情况&#xff0c;莫急…

Xshell 的基本使用

软件长这样 Xshell 链接地址 一、输入 ifconfig 查看 linux ip 地址 二、远程连接服务器 三、测试连接

Java中String类的concat方法___java的String字符串的concat()方法连接字符串和“+“连接字符串解释

Java中String类的concat方法 在了解concat&#xff08;&#xff09;之前&#xff0c;首先需要明确的是String的两点特殊性。 长度不可变值不可变 这两点从源码中对String的声明可以体现&#xff1a; private final char[] value ;其中final对应值的不可更改的特性&#xff1b…

大于小于优化_架构 - 以MySQL为例,详解数据库索引原理及深度优化

一、摘要本文以MySQL数据库为研究对象&#xff0c;讨论与数据库索引相关的一些话题。特别需要说明的是&#xff0c;MySQL支持诸多存储引擎&#xff0c;而各种存储引擎对索引的支持也各不相同&#xff0c;因此MySQL数据库支持多种索引类型&#xff0c;如BTree索引&#xff0c;哈…

c++byte数组和文件的相互转换_终于!word、excel、ppt文件相互转换技巧来了!

不知道大家在用Office软件的时候&#xff0c;有没有遇到过这样的问题。做了个Word文档总结&#xff0c;却需要转换成PPT上台汇报&#xff1b;做了个Word表格统计&#xff0c;却需要转换成Excel进行分析&#xff1b;做了个Excel图表分析&#xff0c;却需要放到Word或PPT上&#…

java多线程之ThreadLoal详解

一、ThreadLocal简介 多线程访问同一个共享变量时特别容易出现并发问题&#xff0c;特别是在多个线程需要对一个共享变量进行写入时。为了保证线程安全&#xff0c;一般使用者在访问共享变量时需要进行适当的同步 同步一般是通过加锁来实现的,但这对用户有一定要求,加重了使用…

JVM经典五十问

文章目录1.什么是JVM?内存管理2.能说一下JVM的内存区域吗&#xff1f;3.说一下JDK1.6、1.7、1.8内存区域的变化&#xff1f;4.为什么使用元空间替代永久代作为方法区的实现&#xff1f;5.对象创建的过程了解吗&#xff1f;6.什么是指针碰撞&#xff1f;什么是空闲列表&#xf…

增量更新同步_OneDrive增量更新功能正式推出 仅同步文件更改部分降低网络占用...

微软的云存储应用OneDrive目前用户量还是蛮多的&#xff0c;不过在功能更新方面OneDrive动作相对来说还是有些慢的。比如非常实用的增量更新功能直到最近微软才正式推出&#xff0c;现在所有个人和企业级用户都可以使用增量更新功能喽。增量更新功能还是有网友在 2014 年向微软…

Vue 封装的过渡与动画

一、作用&#xff1a;在插入、更新或移除DOM元素时&#xff0c;在合适的时候给元素添加样式类名 二、图示 三、写法&#xff1a; 元素进入的样式 v-enter | v-enter-active | v-enter-to元素离开的样式 v-leave | v-leave-active | v-leave-to使用 transition 包裹要过渡的元…

使用navicat for mysql 创建外键foreign keys时,总会自动创建索引indexs

使用navicat for mysql 创建外键foreign keys时&#xff0c;总会自动创建索引indexs。如果删除这个索引就会提示错误error 1553:cann’t drop index…:needed in a foreign key constraint。请教各位&#xff0c;该如何解决呢&#xff0c;不想要indexs 这个好像必须要吧 主键默…

固定 顶部_优质的阳光板温室的顶部应该如此安装,专业的人做专业的事

阳光板温室多为文洛型&#xff0c;多采用一跨多顶&#xff0c;外形现代&#xff0c;结构稳定&#xff0c;形式美观大方&#xff0c;视觉流畅&#xff0c;保温性能卓越&#xff0c;透光率适中&#xff0c;多雨槽&#xff0c;大跨度&#xff0c;排水量大&#xff0c;抗风能力强&a…

json对象、json字符串的区别和相互转换

开发时&#xff0c;json字符串和json对象傻傻分不清楚&#xff0c;ajax异步请求后&#xff0c;会根据返回的data值判断请求是否成功&#xff0c;访问data.msg会提示‘undefined’&#xff0c;将data转换为json对象即可。 一、json对象、json字符串的区别 1、json对象 json对…