8

浮点值是不精确的,这就是为什么我们应该在比较中很少使用严格的数值相等。例如,在 Java 中会打印false如在 ideone.com 上看到的):

System.out.println(.1 + .2 == .3);
// false

通常比较浮点计算结果的正确方法是查看与某个期望值的绝对差是否小于某个可容忍的epsilon

System.out.println(Math.abs(.1 + .2 - .3) < .00000000000001);
// true

问题是某些操作是否可以产生准确的结果。我们知道,对于任何非有限浮点值x(即要么NaN或无穷大),x - x总是ALWAYS NaN

但如果x是有限的,这是否有任何保证?

  1. x * -1 == -x
  2. x - x == 0

(特别是我对 Java 行为最感兴趣,但也欢迎讨论其他语言。)


对于它的价值,我认为(我可能在这里错了)答案是肯定的!我认为这归结为对于任何有限的 IEEE-754浮点值,它的加法逆是否总是可以精确计算。由于 egfloatdouble一个专门用于符号的位,因此似乎就是这种情况,因为它只需要翻转符号位即可找到加法逆元(即有效数字应保持不变)。

相关问题

4

2 回答 2

3

IEEE 754 浮点数保证了这两个等式,因为两者的结果都x-x可以x * -1精确地表示为与 具有相同精度的浮点数x。在这种情况下,无论舍入模式如何,都必须由兼容的实现返回确切的值。

编辑:与.1 + .2示例相比。

您无法在 IEEE 754 中添加.1.2,因为您无法将它们表示为传递给+. 加法、减法、乘法、除法和平方根返回唯一的浮点值,根据舍入模式的不同,该浮点值位于紧接下方、紧接上方、最接近的规则以处理平局,...,运算的结果R中的相同论点。因此,当结果(在R中)恰好可以表示为浮点数时,无论舍入模式如何,该数字都会自动成为结果。

您的编译器允许您0.1在没有警告的情况下编写不同的、可表示的数字的简写,这一事实与这些操作的定义正交。- (0.1)例如,当您编写时, the-是精确的:它返回的参数与其参数完全相反。另一方面,它的参数不是0.1,而是double你的编译器使用的。

x * (-1)简而言之,操作准确的另一部分原因是-1可以表示为double.

于 2010-08-30T10:38:37.983 回答
2

虽然x - x可能会给您-0而不是 true 0,但-0比较等于0,因此您可以放心地假设任何有限数减去自身将比较等于零。

请参阅是否存在 x 的浮点值,其中 xx == 0 为假?更多细节。

于 2010-08-30T12:32:04.593 回答