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);
}
输出:
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()的主要内容,如果未能解决你的问题,请参考以下文章
Apache Spark Reduce 与 java.lang.Math.max 意外行为