首页 > 编程语言 >Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

时间:2023-06-01 16:57:42浏览次数:59  
标签:禁止 Java BigDecimal double equals 使用 new

场景

阿里Java开发手册嵩山版中明确指出:

1、BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法

equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度

2、禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象

BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

Java开发手册为什么禁止使用BigDecimal的equals方法做等值比较?

BigDecimal,相信对于很多人来说都不陌生,很多人都知道他的用法,这是一种java.math 包中提供的一种可以用来

进行精确运算的类型。在进行金额表示、金额计算等场景,不能使用 double、float 等类型,而是要使用对精度支持

更好的 BigDecimal。其内部自带了很多方法,如加,减,乘,除等运算方法都是可以直接调用的。除了需要用

BigDecimal 表示数字和进行数字运算以外,代码中还经常需要对于数字进行相等判断。Java开发手册中有说明:

BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法

equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度。

看下面的示例:

        BigDecimal bigDecimal = new BigDecimal(1);
        BigDecimal bigDecimal1 = new BigDecimal(1);
        System.out.println(bigDecimal.equals(bigDecimal1));//true

        BigDecimal bigDecimal2 = new BigDecimal(1);
        BigDecimal bigDecimal3 = new BigDecimal(1.0);
        System.out.println(bigDecimal2.equals(bigDecimal3));//true

        BigDecimal bigDecimal4 = new BigDecimal("1");
        BigDecimal bigDecimal5 = new BigDecimal("1.0");
        System.out.println(bigDecimal4.equals(bigDecimal5));//false

通过以上代码示例,我们发现,在使用 BigDecimal 的 equals 方法对 1 和 1.0 进行比较的时候,

有的时候是 true(当使用 int、double 定义 BigDecimal 时),有的时候是false(当使用 String 定义 BigDecimal 时)。

查看源码可知,equals会比较标度scale,见源码

 

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

BigDecimal(int) 因为是整数,所以标度就是 0

BigDecimal(double) 无论我们使用 new BigDecimal(0.1)还是 new BigDecimal(0.10)定义,他的近似值

都是0.1000000000000000055511151231257827021181583404541015625

这个,那么他的标度就是这个数字的位数,即 55

BigDecimal(long) 因为是整数,所以标度就是 0

BigDecimal(String)  BigDecimal(“1”)和 BigDecimal(“1.0”)的标度不一样

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

BigDecimal bigDecimal6 = new BigDecimal("1");

BigDecimal bigDecimal7 = new BigDecimal("1.0000");

System.out.println(bigDecimal6.compareTo(bigDecimal7)); //0

Java开发手册为什么禁止使用double直接构造BigDecimal

Java开发手册中要求 禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象

说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常

比如下面,实际存储值为0.10000000149

BigDecimal bigDecimal = new BigDecimal(0.1F);

 

优先推荐入参为String 的构造方法,或使用BigDecimal的valueOf方法,此方法其实内部执行了Double的toString,

而Double的toString按double的实际能表达的精度对尾数进行了截断。

BigDecimal bigDecimal1 = new BigDecimal("0.1");

BigDecimal bigDecimal2 = BigDecimal.valueOf(0.1);

 

 

Java中doble为什么不精确?

十进制小数转成二进制,一般采用”乘 2 取整,顺序排列”方法,如 0.625 转成二进制的表示为 0.101。

但是,并不是所有小数都能转成二进制,如 0.1 就不能直接用二进制表示,他的二进制是 0.000110011001100...

这是一个无限循环小数。所以,计算机是没办法用二进制精确的表示 0.1 的。也就是说,在计算机中,

很多小数没办法精确的使用二进制表示出来。在 Java 中,使用 float 和 double 分别用来表示单精度浮点数和双精度浮点数。

所谓精度不同,可以简单的理解为保留有效位数不同。采用保留有效位数的方式近似的表示小数。

标签:禁止,Java,BigDecimal,double,equals,使用,new
From: https://www.cnblogs.com/badaoliumangqizhi/p/17449546.html

相关文章

  • java.lang.ClassNotFoundException: weblogic.utils.NestedException
    我单元测试的时候报这种错误Causedby:java.lang.ClassNotFoundException:weblogic.utils.NestedException atjava.net.URLClassLoader$1.run(URLClassLoader.java:202) atjava.security.AccessController.doPrivileged(NativeMethod) atjava.net.URLClassLoader.findC......
  • Java学习问题记录
    1.特殊基本数据类型除了这两个,其他的变量都不需要加符号//定义时需要在变量的值后面加L或llongcount=300000L;//定义时需要在变量的值后面加f或Ffloatcode=10.3f;2.常量定义//在Java中使用final关键字来修饰常量,声明方式和变量类似:(通常使用大写字母表示常量)fina......
  • 5.部署tomcat+war包的java网页项目
    1.将war包丢到tomcat-webapps目录下2.修改war包下的数据库配置文件:datasource.propertiescd/usr/local/tomcat/apache-tomcat-8.5.41/webapps/recruit.students/WEB-INF/classesvidatasource.properties 3.用dbeaver连接数据库并导入数据库文件   点击恢复数据库......
  • 新版idea快捷键总结学习----(用于java开发模式)
    选择代码区ctrlw如果放到以if开头的语句,可以选择if判断条件所在的代码片段游标在单个单词下时选择单词在选中多个单词时,选择整个字符串三次点击时,如果不在字符串单词下,用于选择{}内的代码片段逐级递增如果在单词下方,用于选择单词所在的字符串并且向外逐级扩展。ctrl......
  • z-index控制层级显示【JavaScript-Dom&Bom】
    溢出设置overflowvisible(默认)超出部分显示hidden超出部分隐藏scroll超出部分滚动显示行内元素垂直对齐方式vertical-alignbaseline基线对齐(默认)top上对齐middle中间对齐bottom下对齐控制显示层级当元素为非static定位时,可能出现层叠......
  • Java小白入门学习方法总结
    系统的整理了我自学Java的学习方法,希望对大家自学Java有帮助~首先,需要一套系统完整的学习教程,这里推荐可以到b站,我看的动力节点老杜的Java基础课,现在更新了最新版Java17的,可直接看最新版,小白无脑入,详细且全面学习地址:https://www.bilibili.com/video/BV1ig4y1c7kPJava小白学习......
  • java 打印个三角形
    publicclassImoocStudent{publicstaticvoidmain(String[]args)throwsException{intline=9;for(inti=1;i<=line;i++){for(intk=0;k<line-i;k++){System.out.print("");......
  • Java零基础学习方法总结
    系统的整理了我自学Java的学习方法,希望对大家自学Java有帮助~首先,需要一套系统完整的学习教程,这里推荐可以到b站,我看的动力节点老杜的Java基础课,现在更新了最新版Java17的,可直接看最新版,小白无脑入,详细且全面学习地址:https://www.bilibili.com/video/BV1ig4y1c7kPJava小白学习方法......
  • couldn't clear tomcat cache java.lang.NoSuchFieldException: resourceEntries
    2015-09-2500:17:11,435WARN[dqapp24http-nio-8002-exec-22]com.opensymphony.xwork2.util.LocalizedTextUtilcouldn'tcleartomcatcachejava.lang.NoSuchFieldException:resourceEntriesatjava.lang.Class.getDeclaredField(Class.java:2062)~[na:1.8......
  • java 批量数据插入数据库时,加上@Transactional注解后太慢,导致卡死
    这里推荐一个可行的处理方式:新建一张temp表,读取文件先插入temp表,不加注解进行事务处理,这样报错也不会导致正式表的数据被更新掉;数据到插入进temp表后,将temp表数据插入正式表,加上注解,这样可以满足插入大量数据的要求 有更好的方式欢迎评论分享......