Why is Java’s double/float Math.min() implemented this way?

Floating-point numbers are way more complicated than integer values.

For this specific case two distinctions are important:

  • NaN is a valid value for float and double which represents “not a number” and behaves weirdly. Namely, it doesn’t compare equal to itself.
  • Floating point numbers can differentiate between 0.0 and -0.0. A negative zero could conceivably be useful when you’re calculating the limit of some function. Distinguishing whether a limit approaches 0 from the positive or the negative direction could be beneficial.

So this part:

if (a != a) {
      return a;
}

ensures that NaN is returned if a is NaN (if a is not NaN, but b is, then the “normal” check later on will return b, i.e. NaN, so no explicit check is needed for this case). This is a common pattern: when calculating anything where one input is NaN, the output will also be NaN. Since NaN usually represents some error in the calculation (such as dividing 0 by 0), it’s important that it “poisons” all further calculations to ensure the error isn’t silently swallowed.

This part:

if (a == 0.0F && b == 0.0F && (long)Float.floatToRawIntBits(b) == negativeZeroFloatBits) {
      return b;
}

ensures that if you compare two zero-valued floating point numbers and b is negative zero then that negative zero is returned (since -0.0 is “smaller” than 0.0). Similarly to NaN the normal check will correctly return a if it’s -0.0 and b is 0.0.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)