浮点数的基本数据类型不能用==比较,包装数据类型不能用 equals 比较

浮点数的表示

在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示。在Java中,单精度浮点数float类型占32位,它的二进制表示方式为:

  • 符号位:1位,0表示正数; 1表示负数
  • 指数位:8位,用来表示指数(要加上偏移量)
  • 小数位:23位,用来表示小数

实际上计算机中的浮点数表示方法和科学技术法类似,小数的位数决定了浮点数的精度。当一个十进制的小数转换成二进制时,很有可能无法使用这么多小数位表示它。因此使用浮点数的时候,实际存储的尾数是被截取或者舍入之后的值。因此使用浮点数进行计算的时候就不得不考虑精度问题,即浮点数无法精确计算。

如何比较浮点数

1. 不能使用==

对于浮点数,我们无法使用==或者包装类型的equals()来精确比较。例如:

// 对f1执行11次加0.1的操作
float f1 = 0.0f;
for (int i = 0; i < 11; i++) {
f1 += 0.1f;
}
// f2是0.1*11的结果
float f2 = 0.1f * 11;
System.out.println(f1 == f2); // 结果为false

执行上述代码,会得到二者不相等,同时如果打印f1和f2,会得到如下结果:

f1 = 1.1000001
f2 = 1.1

可以看到,在浮点数的运算过程中,确实出现了精度问题。

2. 规定误差范围

尽管无法做到精确比较,但是我们可以确定一个误差范围,当小于这个误差范围的时候就认为这两个浮点数相等。例如:

final float THRESHOLD = 0.000001;   // 设置最大误差不超过0.000001
float f1 = 0.0f;
for (int i = 0; i < 11; i++) {
f1 += 0.1f;
} float f2 = 0.1f * 11; if (Math.abs(f1 - f2) < THRESHOLD) {
System.out.println("f1 equals f2");
}

3. 使用BigDecimal

BigDecimal是一个不可变的、能够表示大的十进制整数的对象。注意使用BigDecimal时,要使用参数为String的构造方法,而不要使用参数为double的构造方法,防止产生精度丢失。使用BigDecimal进行运算,使用它的compareTo()方法比较即可。

示例:

private void compareByBigDecimal() {
BigDecimal f1 = new BigDecimal("0.0");
BigDecimal pointOne = new BigDecimal("0.1");
for (int i = 0; i < 11; i++) {
f1 = f1.add(pointOne);
} BigDecimal f2 = new BigDecimal("0.1");
BigDecimal eleven = new BigDecimal("11");
f2 = f2.multiply(eleven); System.out.println("f1 = " + f1);
System.out.println("f2 = " + f2); if (f1.compareTo(f2) == 0) {
System.out.println("f1 and f2 are equal using BigDecimal");
} else {
System.out.println("f1 and f2 are not equal using BigDecimal");
}
}

参考链接

Java比较两个浮点数的更多相关文章

  1. java中float/double浮点数的计算失精度问题(转)

    如果我们编译运行下面这个程序会看到什么? public class Test  {    public static void main(String args[]) {                ...

  2. Java的两大数据类型

    Java的两大数据类型 基本数据类型 byte,short,int,long,float,double,boolean,char byte 类别 内容 类型 byte 简介 byte 数据类型是8位. ...

  3. 有趣的Java之调皮的浮点数

    **当你在写一个电商网站的时候,你可能会给你的商品标价1.99,10.9这样的价格来吸引顾客.我应该用浮点数float/double来储存它们,当我的顾客购买商品的时候,从他们的账户里扣费,使用整型是 ...

  4. Java如何正确比较浮点数

    看下面这段代码,将 d1 和 d2 两个浮点数进行比较,输出的结果会是什么? double d1 = .1 * 3; double d2 = .3; System.out.println(d1 == ...

  5. java使double保留两位小数的多方法 java保留两位小数

    这篇文章主要介绍了java使double类型保留两位小数的方法,大家参考使用吧 复制代码 代码如下: mport java.text.DecimalFormat; DecimalFormat    d ...

  6. java比较两个对象是否相等的方法

    java比较两个对象是否相等直接使用equals方法进行判断肯定是不会相同的. 例如: Person  person1  =new Person("张三"); Person  pe ...

  7. java保留两位小数

    java保留两位小数问题: 方式一: 四舍五入  double   f   =   111231.5585;  BigDecimal   b   =   new   BigDecimal(f);  d ...

  8. java中两种类型变量

    Java中有两种类型的变量,一种是对象类型,另一种是基础类型(primitive type). 对象类型普遍采用引用的方式,比如 List a = new ArrayList(); List b = ...

  9. JAVA 中两种判断输入的是否是数字的方法__正则化_

    JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengz ...

随机推荐

  1. MapReduce框架原理--Shuffle机制

    Shuffle机制 Mapreduce确保每个reducer的输入都是按键排序的.系统执行排序的过程(Map方法之后,Reduce方法之前的数据处理过程)称之为Shuffle. partition分区 ...

  2. 神经网络:numpy实现神经网络框架

    欢迎访问个人博客网站获取更多文章: https://beityluo.space 本文用numpy从零搭建了一个类似于pytorch的深度学习框架 可以用于前面文章提到的MINST数据集的手写数字识别 ...

  3. MeteoInfo-Java解析与绘图教程(三)

    MeteoInfo-Java解析与绘图教程(三) 上文我们说到简单绘制色斑图(卫星云图),但那种效果可定不符合要求,一般来说,客户需要的是在地图上色斑图的叠加,或者是将图片导出分别是这两种效果 当然还 ...

  4. 并发编程 Process 互斥锁

    进程理论 程序与进程的区别 ''' 程序不是存在硬盘上的代码,相对来说是静态的 进程表示程序在执行的过程,是动态的 ''' 进程的调度 先来先服务调度算法 '''对长作业有利,对短作业无益''' 短作 ...

  5. SQL 练习37

    检索至少选修两门课程的学生学号 SELECT Student.SId,Student.Sname,选课数 from Student, (SELECT sid,COUNT(cid) 选课数 from s ...

  6. 安装 iperf和服务器之间测速

    安装 # https://downloads.es.net/pub/iperf/iperf-3.1.3.tar.gz wget https://iperf.fr/download/source/ipe ...

  7. html,javascript,正则表达式

    正则表达式是对字符串操作的逻辑公式,用事先定好的一些特定字符组成一个"规则字符串",在用"规则字符串"对字符串进行过滤. ECMAScript 通过RegExp ...

  8. 编写一个简单的COM组件

    参考网站:编写一个简单的COM组件_a ray of sunshine-CSDN博客 (1) 用MIDL编写.idl文件 //将以下代码保存成 IXIYIZ.idl 文件 //在命令行上进行编译,编译 ...

  9. 【mysql】关联查询_子查询_排序分组优化

    1. 关联查询优化 1.1 left join 结论: ①在优化关联查询时,只有在被驱动表上建立索引才有效! ②left join 时,左侧的为驱动表,右侧为被驱动表! 1.2 inner join ...

  10. [SWMM]软件启动不了,出现 “ RPC服务器不可用 ” 错误

    [问题]打开SWMM5.1软件时,初选"RPC服务器不可用"的错误 [解决]计算机管理--服务 设置Print Spooler服务状态为启动,并设置为自启动.