当前位置: 首页 > 面试题库 >

直接在Java中比较2个float / double是否安全?

贺轶
2023-03-14
问题内容

如果我使用像这样的比较(a是int,b和c是float / double)是否安全:

a == b
b == c

它可能听起来很荒谬,但是在我的旧编程语言中,有时1 + 2 == 3是错误的(因为左侧返回2.99999999999 …)。而且,这呢:

Math.sqrt(b) == Math.sqrt(c)
b / 3 == 10 / 3 //In case b = 10, does it return true?

问题答案:

通常,由于不能精确地将许多十进制数字表示为floator
double值,因此这样做并不安全。经常陈述的解决方案是测试数字之间的差异是否小于某个“小”值(在数学文献中通常用希腊字母“ epsilon”表示)。

但是 -您需要稍微小心如何进行测试。例如,如果您编写:

if (Math.abs(a - b) < 0.000001) {
    System.err.println("equal");
}

ab应该是“相同”的地方,您正在测试 绝对错误 。如果这样做,可能会遇到麻烦,如果ab分别是和(say_
1,999,999.992,000,000.00。这两个数字之间的差小于a的 该标度下该尺度下
的最小可表示值float,但比我们选择的epsilon大得多。

可以说,更好的方法是使用 相对误差 。例如(防御性地)编码为

if (a == b ||
    Math.abs(a - b) / Math.max(Math.abs(a), Math.abs(b)) < 0.000001) {
    System.err.println("close enough to be equal");
}

但这甚至不是一个完整的答案,因为它没有考虑某些计算导致错误累积到无法控制的比例的方式。请查看此Wikipedia链接以了解更多详细信息。

最重要的是,处理浮点计算中的错误比乍一看要困难得多。

需要注意的另一点是(正如其他人所解释的那样)整数算法在两个方面与浮点算法有很大不同:

  • 如果结果不是整数,整数除法将截断
  • 整数加法减法和乘法将溢出。

这两种情况在编译时或运行时都 不会发出任何警告



 类似资料:
  • 问题内容: 我碰到了Java的一个奇怪角落(对我来说似乎很奇怪) o / p:是 o / p:错误 我观察到,如果我们将任意两个值(如我在示例中提到的float和double)与OR 进行比较,例如3.5、234.5、645.0,则输出为即两个值相等,否则输出为相等。 甚至我都试着做方法,但是没有运气。我错过了什么吗? 问题答案: 看一下每位计算机科学家应该了解的浮点数。 将无限多个实数压缩为有限

  • 这是一个Java代码,应该测试小数点后的前三位是否相同。而我需要编写这个程序没有一个主方法。

  • 问题内容: Utilities.getDistance返回double,而getAttackRange返回int。上面的代码是if语句的一部分,它必须为true。那比较有效吗? 谢谢 问题答案: 是的,它是有效的-这将推动到执行比较之前。 请参阅JLS第15.20.1节(数值比较运算符),该链接链接到JLS第5.6.2节(二进制数值提升)。 从后者: 扩展原语转换(第5.1.2节)适用于转换以下规

  • 问题内容: Java中两个double值的简单比较会产生一些问题。让我们考虑以下Java中的简单代码段。 上面的代码似乎返回,表达式的求值,但是没有。它之所以返回,是因为该表达式的求值实际上是预期的因此不等于,因此条件的求值为。解决这种情况的最佳建议方法是什么? 问题答案: 基本上,你不应该进行精确比较,而应该执行以下操作:

  • 我有这段Java代码: 是否保证在控制台上打印?我的意思是,是通过值(这是我需要做的)还是通过引用标识来比较两个装箱的整数? 另外,如果我将它们转换为未装箱的整数,会有什么不同吗

  • 问题内容: 比较浮点数和这样的整数是否安全? 根据JLS(5.6.2。二进制数值提升),如果其中一个参数为,则另一个参数将转换为比较之前的值。但是据我了解,如果转换后的float与原始float二进制相同,则这样的比较将返回true。我们如何确保呢? 问题答案: 是的,您的具体示例很好,因为和都可以精确地表示为。 请注意,通常情况下并非如此:有很多大值无法完全表示为。例如,即使2_000_000_