行业资讯 2025年08月6日
0 收藏 0 点赞 205 浏览 2704 个字
摘要 :

文章目录 1.比较double – 简单比较【不推荐】 2.比较double – 基于阈值的比较【推荐】 3.比较double – 使用BigDecimal比较【推荐】 正确比较 float……




  • 1.比较double – 简单比较【不推荐】
  • 2.比较double – 基于阈值的比较【推荐】
  • 3.比较double – 使用BigDecimal比较【推荐】

正确比较 float比较 double不仅仅是 Java 特有的问题。如今几乎所有编程语言中都可以观察到这一点。在计算机内存中,浮点数和双精度数使用IEEE 754标准格式存储。实际存储和转换如何工作,超出了本文的范围。

现在,只需了解在计算和转换过程中,这些数字可能会引入较小的舍入误差。这就是为什么不建议简单地依赖相等运算符 (==)来比较浮点数

让我们学习如何在 Java 中比较浮点值

1.比较double – 简单比较【不推荐】

首先看一下简单的比较方法,以了解使用==运算符比较double时出现了什么问题。在给定的程序中,我使用两种方法创建相同的浮点数(即1.1):

  • 将0.1累加11次。
  • 将0.1乘以11。

理论上,这两种操作都应该生成数字1.1。当我们比较这两种方法的结果时,它们应该匹配。

private static void simpleFloatsComparison() 
{
  //Method 1
  double f1 = .0;
  for (int i = 1; i <= 11; i++) {
    f1 += .1;
  }
 
  //Method 2
  double f2 = .1 * 11;
 
  System.out.println(\"f1 = \" + f1);
  System.out.println(\"f2 = \" + f2);
 
  if (f1 == f2)
    System.out.println(\"f1 and f2 are equal\\n\");
  else
    System.out.println(\"f1 and f2 are not equal\\n\");
}

程序输出:

f1 = 1.0999999999999999
f2 = 1.1
f1 and f2 are not equal

查看控制台中打印的两个值。f1计算为1.0999999999999999. 这正是四舍五入内部导致的问题。这就是为什么不建议使用运算\'==\'进行浮点数比较的原因

2.比较double – 基于阈值的比较【推荐】

现在我们知道了等号运算符的问题,让我们来解决它。在编程中,我们不能改变这些浮点数的存储或计算方式。因此,我们必须采用一种解决方案,其中我们同意确定两个值之间的差异,我们可以容忍并仍然将这些数字视为相等。这些值之间的同意差异称为阈值或epsilon。

因此,为了使用“基于阈值的浮点数比较”,我们可以使用Math.abs()方法计算两个数字之间的差异,然后将差异与阈值进行比较。这样做可以确保我们在比较浮点数时考虑到了精度差异。

private static void thresholdBasedFloatsComparison() 
{
  final double THRESHOLD = .0001;
 
  //Method 1
  double f1 = .0;
  for (int i = 1; i <= 11; i++) {
    f1 += .1;
  }
 
  //Method 2
  double f2 = .1 * 11;
 
  System.out.println(\"f1 = \" + f1);
  System.out.println(\"f2 = \" + f2);
 
  if (Math.abs(f1 - f2) < THRESHOLD)
    System.out.println(\"f1 and f2 are equal using threshold\\n\");
  else
    System.out.println(\"f1 and f2 are not equal using threshold\\n\");
}

程序输出:

f1 = 1.0999999999999999
f2 = 1.1
f1 and f2 are equal using threshold

3.比较double – 使用BigDecimal比较【推荐】

在BigDecimal类中,您可以指定要使用的舍入模式和精确度限制。使用精确度限制,舍入误差大多可以解决。

最重要的一点是,BigDecimal数字是不可变的,即如果您创建了一个值为“1.23”的BigDecimal对象BD,那么该对象将始终是“1.23”,永远不会更改。此类提供了许多方法,可用于对其值进行数值操作。

您可以使用其compareTo()方法来比较两个BigDecimal数字。在比较时,它忽略了标度(小数点后的位数)。

a.compareTo(b);

方法返回:

-1:如果a<b

0 :如果 a == b

1 : 如果 a > b

永远不要使用equals()方法来比较BigDecimal实例。这是因为这个equals函数将比较它们的标度(scale)。如果标度不同,equals()会返回false,即使它们在数学上是相同的数字。

使用BigDecimal类的compareTo方法来比较double值:

private static void testBdEquality() 
{
   BigDecimal a = new BigDecimal(\"2.00\");
   BigDecimal b = new BigDecimal(\"2.0\");
 
   System.out.println(a.equals(b));       // false
 
   System.out.println(a.compareTo(b) == 0);   // true
}

现在,只是为了验证,让我们使用 BigDecimal 类来解决原始问题:

private static void bigDecimalComparison() 
{
  //Method 1
  BigDecimal f1 = new BigDecimal(\"0.0\");
  BigDecimal pointOne = new BigDecimal(\"0.1\");
  for (int i = 1; i <= 11; i++) {
    f1 = f1.add(pointOne);
  }
 
  //Method 2
  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\\n\");
  else
    System.out.println(\"f1 and f2 are not equal using BigDecimal\\n\");
}

程序输出:

f1 = 1.1
f2 = 1.1
f1 and f2 are equal using BigDecimal

这就是java 中比较浮点数的全部内容。在评论部分分享您的想法。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9202.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号