Hmm.


Since NaN is neither greater than nor less that anything, it seems the only correct answer to any
Min,max,clamp involving a NaN is NaN.

-CHB


On Sat, Jul 4, 2020 at 9:15 AM Ben Rudiak-Gould <benrudiak@gmail.com> wrote:
On Fri, Jul 3, 2020 at 5:07 PM Steven D'Aprano <steve@pearwood.info> wrote:
> As I recall, there was some positive support but it ran out of steam
> because nobody could agree on how to handle NANs even though the
> IEEE-754 standard tells us how to handle them *wink*
>
> See my responses at the time re NANs here:
>
> https://mail.python.org/pipermail/python-ideas/2016-August/041439.html
>
> https://mail.python.org/pipermail/python-ideas/2016-August/041400.html
>
> https://mail.python.org/pipermail/python-ideas/2016-August/041396.html
>
> Bottom line is that passing a NAN as the lower or upper bound should
> treat it as equivalent to "unbounded", that is, equivalent to ±∞.

That's not what the standard says. It's sorta connected to a personal
opinion of Kahan's expressed in some work-in-progress lecture notes
that you linked in the last message:

    https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

What he says there (on page 9) is

>Some familiar functions have yet to be defined for NaN . For instance max{x, y} should deliver the same result as max{y, x} but almost no implementations do that when x is NaN . There are good reasons to define max{NaN, 5} := max{5, NaN} := 5 though many would disagree.

It's clear that he's not referring to standard behavior here and I'm
not convinced that even he believes very strongly that min and max
should behave that way.

NaN means "there may be a correct answer but I don't know what it is."
For example, evaluating (x**2+3*x+1)/(x+2) at x = -2 yields NaN. The
correct answer to the problem that yielded this formula is probably
-1, but because of the way floating point hardware works, it has no
way of figuring that out. Likewise, the final result of a computation
involving the square root of a negative real may be well defined, and
may even be real, but the hardware can't compute it, so it "computes"
NaN instead.

It's definitely true that if plugging in any finite or infinite number
whatsoever in place of a NaN will yield the same result, then that
should be the result when you plug in a NaN. For example, clamp(x,
NaN, x) should be x for every x (even NaN), and clamp(y, NaN, x) where
y > x should be a ValueError (or however invalid bounds are treated).

But, e.g., clamp(m, x, M) where m < x could yield any value between m
and x, or a ValueError, depending on the value of M. So, if M is NaN,
there is no way to know what the correct answer should be. Therefore
(in my opinion) it should return NaN.

There's a case for making clamp(m, x, NaN) where m >= x return m
rather than NaN since there's no other *value* it could be (it could
be an exception though).
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/PHH7EYAWJBKJCCMPU4KCROKDC3BYACWD/
Code of Conduct: http://python.org/psf/codeofconduct/
--
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython