# When is min(a, b) != min(b, a)?

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Mon Jan 21 10:06:44 CET 2008

On Sun, 20 Jan 2008 21:15:02 -0600, Albert Hopkins wrote:

> This issue may have been referred to in
> news:<mailman.1864.1196703799.13605.python-list at python.org> but I didn't
> entirely understand the explanation.  Basically I have this:
>
>     >>> a = float(6)
>     >>> b = float('nan')
>     >>> min(a, b)
>     6.0
>     >>> min(b, a)
>     nan
>     >>> max(a, b)
>     6.0
>     >>> max(b, a)
>     nan
>
> Before I did not know what to expect, but I certainly didn't expect
> this.  So my question is what is the min/max of a number and NaN or is
> it not defined (for which I would have expected either an exception to
> be raised or NaN returned in each case).

According to the IEEE-754 standard the usual trichotomy of "x is less
than y, x is equal to y, or x is greater than y" has to be extended to
include "x and y are unordered". Comparisons with NaNs are unordered, and
so expressions like "x < nan" should signal an exception.

(However both == and != do not signal exceptions, they return False and
True respectively.)

Unfortunately, the standard conflicts with Python's requirement that
comparisons should always return True or False, so the next "least bad"
alternative is to have comparisons with NaN to return False. That is:

>>> 5 < float('nan')
False
>>> 5 >= float('nan')
False

So BEWARE of assuming that if x < y returns False, y >= x must return
True. That does not hold for floats.

Aside: Apple's Power PC Numerics math library extended the usual six
comparison operators to fourteen. I don't judge whether this was a good
idea or not.

http://developer.apple.com/documentation/mac/PPCNumerics/PPCNumerics-37.html#MARKER-9-1

Given that NaNs are unordered, the "right" thing for max() and min() to
do is raise an exception. But failing that, the next best thing would be
for them to ignore any NaNs. Any way you look at it, for min or max to
return a nan is a mistake. Possibly even a bug.

> As a corrollary would I be able to rely on the above behavior or is it
> subject to change (to fix a bug in min/max perhaps :-)?

Presently, you can't rely on *any* behaviour of NaNs and INFs in Python,
since they all depend on the underlying C library. Even whether or not
you can create them is not defined in Python.

--
Steven