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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java:添加/减去Math.ulp()与Math.nextAfter()相关的知识,希望对你有一定的参考价值。

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

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

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

答案

这个程序:

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)被定义为返回“此浮点值与下一个更大的双值之间的正距离”,因此当距离不同时,减法命题为假。

另一答案

我认为要检查的直接情况是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也不正确(参见最后一栏)。

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

以上是关于Java:添加/减去Math.ulp()与Math.nextAfter()的主要内容,如果未能解决你的问题,请参考以下文章

java中的当前时间减去天数

Java中Math对象的属性与方法

Apache Spark Reduce 与 java.lang.Math.max 意外行为

java 取范围内的随机数,比如取10000至99999

ACM-ICPC 2018 徐州赛区网络预赛 D.easy math

Java-Final 类与私有构造函数:java.util.Arrays 和 java.lang.Math 之间的区别