Java: Adding/Subtracting Math.ulp() vs. Math.nextAfter()
This program:
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));
}
}
outputs:
false
true
The difference between consecutive doubles changes at each normal integer power of two, including 1.0. One of the tests must fail, because it assumes constant difference. Math.ulp(double) is defined to return "the positive distance between this floating-point value and the double value next larger in magnitude" so the subtract proposition is false when the distance is different.
The immediate cases I'd think to check are 0, +infinity and -infinity and 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
Output:
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
That the expressions aren't equal in the NaN
case isn't surprising (by the definition of NaN); but these expressions also aren't true for +infinity and -infinity (see the last column).
This answer is not intended to provide an exhaustive list of problematic values, but rather to show that some problematic values do exist.