Hacker News new | ask | show | jobs
by ridiculous_fish 4383 days ago
This is a lot more subtle than most programmers realize, thanks to floating point weirdness.

An essential property of MIN is that it is symmetric with respect to its arguments: MIN(a, b) and MIN(b, a) are the same thing. But the expression (a < b ? a : b) is not symmetric with NaNs. So what do we do?

We could assert that if only one value is an NaN, we return the other value. We might write it like this:

    if (a != a) return b;
    return a < b ? a : b;
This isn't symmetric if both arguments are different NaNs, but in practice getting different NaNs takes some work. (Note that C99 requires that fmin behave this way with respect to NaN.)

But we're still not quite symmetric, thanks to negative zero. Negative zero compares equal to positive zero, but it doesn't seem right that the sign bit of the result should depend on the argument order.

glibc doesn't bother to handle negative zero, but Java's Math.min does:

    public static double min(double a, double b) {
        if (a != a) return a;
        if ((a == 0.0d) && (b == 0.0d)
            && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) {
            return b;
        }
        return (a <= b) ? a : b;
    }
Delightful. Java has the best min.