Java:添加/减去Math.ulp()与Math.nextAfter()

问题描述 投票:12回答:2

我正在尝试更详细地了解Java中的浮点运算。如果我正确阅读文档,则对于任何给定的双x,以下内容成立:

x - Math.ulp(x) == Math.nextAfter(x, Double.NEGATIVE_INFINITY);
x + Math.ulp(x) == Math.nextAfter(x, Double.POSITIVE_INFINITY);

问题:这种情况总是如此,还是存在一些结果会有所不同的例外情况?

java floating-point
2个回答
10
投票

这个程序:

public class Test {
  public static void main(String[] args) {
    double x = 1;
    System.out.println(x - Math.ulp(x) == Math.nextAfter(x, Double.NEGATIVE_INFINITY));
    System.out.println(x + Math.ulp(x) == Math.nextAfter(x, Double.POSITIVE_INFINITY));
  }
}

输出:

false
true

连续双精度之间的差异在每个正常整数幂为2时变化,包括1.0。其中一项测试必须失败,因为它假设不断有差异。 Math.ulp(double)被定义为返回“此浮点值与下一个更大的双值之间的正距离”,因此当距离不同时,减法命题为假。


4
投票

我认为要检查的直接情况是0,+无穷大和-infinity和NaN:

static void check(double x) {
  double a, b;
  System.out.printf(
      "%9s %9s %23s %5s%n",
      x, a = x - Math.ulp(x), b = Math.nextAfter(x, Double.NEGATIVE_INFINITY), a == b);
  System.out.printf(
      "%9s %9s %23s %5s%n",
      x, a = x + Math.ulp(x), b = Math.nextAfter(x, Double.POSITIVE_INFINITY), a == b);
  System.out.println();
}

public static void main(String[] args) throws java.lang.Exception {
  check(0);
  check(Double.POSITIVE_INFINITY);
  check(Double.NEGATIVE_INFINITY);
  check(Double.NaN);
}

Ideone demo

输出:

      0.0 -4.9E-324               -4.9E-324  true
      0.0  4.9E-324                4.9E-324  true

 Infinity       NaN  1.7976931348623157E308 false
 Infinity  Infinity                Infinity  true

-Infinity -Infinity               -Infinity  true
-Infinity       NaN -1.7976931348623157E308 false

      NaN       NaN                     NaN false
      NaN       NaN                     NaN false

NaN案例中表达式不相等并不令人惊讶(根据NaN的定义);但这些表达式对于+ infinity和-infinity也不正确(参见最后一栏)。

这个答案并不是为了提供有问题的值的详尽列表,而是为了表明存在一些有问题的值。

© www.soinside.com 2019 - 2024. All rights reserved.