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

Discussion in 'Python' started by Albert Hopkins, Jan 21, 2008.

  1. This issue may have been referred to in
    news:<> 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).

    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 :)?
     
    Albert Hopkins, Jan 21, 2008
    #1
    1. Advertising

  2. Albert Hopkins

    Bonjour Guest

    'NaN' means "Not a number". according to Python semantics, if you try
    to compare it with any other float numbers, it should return FALSE.
    just like
    >>>
    >>>1.0 > 'abc'

    False
    >>>

    Since it always return FALSE, it is not a surprise for your question.

    If you wish to get infinitive number, you'd use 'inf' or '-inf', from
    IEEE 754 semantics:
    >>>a=float(6)
    >>>b=float('inf')
    >>>c=float('-inf')



    Albert Hopkins wrote:
    > This issue may have been referred to in
    > news:<> 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).
    >
    > 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 :)?
     
    Bonjour, Jan 21, 2008
    #2
    1. Advertising

  3. Albert Hopkins

    Bonjour Guest

    'NaN' means "Not a number". according to Python semantics, if you try
    to compare it with any other float numbers, it should return FALSE.
    just like:

    >>>1.0 > 'abc'

    False

    Since it always return FALSE, it is not a surprise for your question.

    If you wish to get infinitive number, you'd use 'inf' for positive
    infinitive or '-inf' for negative infinitive, from
    IEEE 754 semantics, just like:

    >>>a=float(6)
    >>>b=float('inf')
    >>>c=float('-inf')


    For more information, PEP-0754 may be helpful.
     
    Bonjour, Jan 21, 2008
    #3
  4. Albert Hopkins

    Paddy Guest

    On Jan 21, 3:15 am, Albert Hopkins <> wrote:
    > This issue may have been referred to in
    > <news:> 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).
    >
    > 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 :)?


    I am definitely NOT a floating point expert, but I did find this:
    http://en.wikipedia.org/wiki/IEEE_754r#min_and_max

    P.S. What platform /Compiler are you using for Python?

    - Paddy.
     
    Paddy, Jan 21, 2008
    #4
  5. On Sun, 20 Jan 2008 20:16:18 -0800, Paddy wrote:

    > I am definitely NOT a floating point expert, but I did find this:
    > http://en.wikipedia.org/wiki/IEEE_754r#min_and_max
    >
    > P.S. What platform /Compiler are you using for Python?


    Linux with GCC 4

    -a
     
    Albert Hopkins, Jan 21, 2008
    #5
  6. On Sun, 20 Jan 2008 21:15:02 -0600, Albert Hopkins wrote:

    > This issue may have been referred to in
    > news:<> 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
     
    Steven D'Aprano, Jan 21, 2008
    #6
  7. Albert Hopkins

    Jason Guest

    On Jan 21, 12:00 am, Albert Hopkins <> wrote:
    > On Sun, 20 Jan 2008 20:16:18 -0800, Paddy wrote:
    > > I am definitely NOT a floating point expert, but I did find this:
    > >http://en.wikipedia.org/wiki/IEEE_754r#min_and_max

    >
    > > P.S. What platform /Compiler are you using for Python?

    >
    > Linux with GCC 4
    >
    > -a


    Please note that NaN's are very funky and platform dependent. They
    depend on their underlying platform's C library for creation and
    display. On windows, "float('nan')" will cause an exception, as there
    are no valid string representations of NAN that can be converted to
    the special floating point value. Also, if you manage to create a nan
    under Windows, it displays as "1.#QNAN".

    Infinite values are also problematic. In almost all cases, it is far
    better to avoid infinite and NaN values.

    --Jason
     
    Jason, Jan 21, 2008
    #7
  8. On Jan 21, 9:55 am, Jason <> wrote:
    > display.  On windows, "float('nan')" will cause an exception, as there
    > are no valid string representations of NAN that can be converted to
    > the special floating point value.  Also, if you manage to create a nan
    > under Windows, it displays as "1.#QNAN".


    I believe this will be fixed in Python 2.6 :)

    Mark
     
    Mark Dickinson, Jan 21, 2008
    #8
  9. On 2008-01-21, Albert Hopkins <> wrote:
    > This issue may have been referred to in
    > news:<> 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).


    For applications I work on, it should be NaN. But I think the
    result of comparing a Normal to a NaN is undefined, so the
    above behavior is allowed by the IEEE spec.

    > 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 :)?


    According to Wikipedia:

    In the proposed IEEE 754r revision of that standard the same
    rule applies, except that a few anomalous functions (such as
    the maxnum function, which returns the maximum of two
    operands which are expected to be numbers) favour numbers --
    if just one of the operands is a NaN then the value of the
    other operand is returned.

    A different approach has been implemented in the NaN
    'toolbox' for GNU Octave and MATLAB. In that toolbox, NaNs
    are assumed to represent missing values and so the
    statistical functions ignore NaNs in the data instead of
    propagating them. Every computation in the NaN toolbox is
    based on the data values only, which can be useful if it is
    known that NaNs cannot be produced by errors.


    --
    Grant Edwards grante Yow! Remember, in 2039,
    at MOUSSE & PASTA will
    visi.com be available ONLY by
    prescription!!
     
    Grant Edwards, Jan 21, 2008
    #9
  10. On 2008-01-21, Jason <> wrote:

    > Infinite values are also problematic. In almost all cases, it is far
    > better to avoid infinite and NaN values.


    In many applications (e.g. process control) propogating NaN
    values are way too useful to avoid. Avoiding NaN would make a
    lot of code far more complicated than would using them.

    --
    Grant Edwards grante Yow! How's the wife?
    at Is she at home enjoying
    visi.com capitalism?
     
    Grant Edwards, Jan 21, 2008
    #10
  11. Albert Hopkins

    Pete Forman Guest

    Grant Edwards <> writes:

    > For applications I work on, it should be NaN. But I think the
    > result of comparing a Normal to a NaN is undefined, so the
    > above behavior is allowed by the IEEE spec.


    Comparison of two floating point datums results in exactly one of
    these being true:

    1) less than
    2) equal
    3) greater than
    4) unordered


    IEEE 754r defines maxNum and minNum which are explicitly defined to
    return one argument if the other is a NaN. Any other operation (apart
    from a few others that are specified) return a NaN if any argument is
    NaN.

    NaN generally represents the result of an invalid operation. Using it
    for missing value is not in the draft standard, though it is not
    forbidden either.

    If NaNs in your data are important then you must take care in explicit
    and implicit comparisons to consider unordered results.
    --
    Pete Forman -./\.- Disclaimer: This post is originated
    WesternGeco -./\.- by myself and does not represent
    -./\.- the opinion of Schlumberger or
    http://petef.port5.com -./\.- WesternGeco.
     
    Pete Forman, Jan 21, 2008
    #11
  12. On Mon, 21 Jan 2008 18:00:05 +0000, Pete Forman wrote:

    > If NaNs in your data are important then you must take care in explicit
    > and implicit comparisons to consider unordered results.


    And even if they're not important, beware of bugs from failing to
    consider unordered results due to unexpected NaNs.



    --
    Steven
     
    Steven D'Aprano, Jan 21, 2008
    #12
  13. math and numerical fixes (was: When is min(a, b) != min(b, a)?)

    Jason wrote:
    > Please note that NaN's are very funky and platform dependent. They
    > depend on their underlying platform's C library for creation and
    > display. On windows, "float('nan')" will cause an exception, as there
    > are no valid string representations of NAN that can be converted to
    > the special floating point value. Also, if you manage to create a nan
    > under Windows, it displays as "1.#QNAN".
    >
    > Infinite values are also problematic. In almost all cases, it is far
    > better to avoid infinite and NaN values.


    CC to Python Dev

    I've fixed that and enhanced the support for NaN and inf for 2.6 and
    3.0. I'm working together with Mark on more NaN and inf related fixes
    and he has fixed some numerical issues in the cmath module. We both hope
    to get Python's math more sound and stable across platforms.

    So far I got float('nan'), float('inf') and float('-inf') working on all
    platforms. The math module got three new methods: isinf, isnan, copysign.

    Additionally the trunk-math branch contains code for inverse hyberbolic
    functions (acosh), log1p, Mark's fixes for complex math and more stuff.
    For example operations on NaNs now return a NaN on all platforms (except
    1**NAN which is defined as 1 and 0**NAN which is defined as 0). In 2.5
    it depends on the platform whether a function raises an exception or
    returns NaN.

    Mark had the nice idea to introduce a thread local or global flag for
    NaN support. Depending on a flag Python turns a NaN into an exception.
    The feature needs a proper PEP. Maybe Mark has time to write a PEP in time.

    Christian
     
    Christian Heimes, Jan 23, 2008
    #13
  14. Grant Edwards wrote:
    > In many applications (e.g. process control) propogating NaN
    > values are way too useful to avoid. Avoiding NaN would make a
    > lot of code far more complicated than would using them.


    NaNs are very useful for experienced power users but they are very
    confusing for newbies or developers without a numerical background.

    It's very easy to create an inf or nan in Python:

    inf = 1E+5000
    ninf = -inf
    nan = inf * 0.

    1E5000 creates a nan because it is *much* bigger than DBL_MAX (around
    1E+308). In fact it is even larger than LDBL_MAX (around 1E+4932).

    Christian
     
    Christian Heimes, Jan 23, 2008
    #14
  15. In article <>,
    Christian Heimes <> wrote:

    > Grant Edwards wrote:
    > > In many applications (e.g. process control) propogating NaN
    > > values are way too useful to avoid. Avoiding NaN would make a
    > > lot of code far more complicated than would using them.

    >
    > NaNs are very useful for experienced power users but they are very
    > confusing for newbies or developers without a numerical background.
    >
    > It's very easy to create an inf or nan in Python:
    >
    > inf = 1E+5000
    > ninf = -inf
    > nan = inf * 0.
    >
    > 1E5000 creates a nan because it is *much* bigger than DBL_MAX (around
    > 1E+308). In fact it is even larger than LDBL_MAX (around 1E+4932).


    Isn't it safer to use float("inf"), float("-inf") and float("nan") to
    create the necessary items?

    -- Russell
     
    Russell E. Owen, Jan 23, 2008
    #15
  16. Albert Hopkins

    Robert Kern Guest

    Russell E. Owen wrote:
    > In article <>,
    > Christian Heimes <> wrote:
    >
    >> Grant Edwards wrote:
    >>> In many applications (e.g. process control) propogating NaN
    >>> values are way too useful to avoid. Avoiding NaN would make a
    >>> lot of code far more complicated than would using them.

    >> NaNs are very useful for experienced power users but they are very
    >> confusing for newbies or developers without a numerical background.
    >>
    >> It's very easy to create an inf or nan in Python:
    >>
    >> inf = 1E+5000
    >> ninf = -inf
    >> nan = inf * 0.
    >>
    >> 1E5000 creates a nan because it is *much* bigger than DBL_MAX (around
    >> 1E+308). In fact it is even larger than LDBL_MAX (around 1E+4932).

    >
    > Isn't it safer to use float("inf"), float("-inf") and float("nan") to
    > create the necessary items?


    In currently-released versions of Python, these are not portable.
    float(some_string) just passes the string to the platform's conversion function.
    There is no standard defining what to do with "nan" or "inf". On Linux, these
    work as intended, but on Windows, they are errors.

    Christian is working on a branch to standardize these forms for Python 2.6. See
    "math and numerical fixes" in this thread.

    --
    Robert Kern

    "I have come to believe that the whole world is an enigma, a harmless enigma
    that is made terrible by our own mad attempt to interpret it as though it had
    an underlying truth."
    -- Umberto Eco
     
    Robert Kern, Jan 23, 2008
    #16
  17. On 2008-01-21, Steven D'Aprano <> wrote:
    > On Sun, 20 Jan 2008 21:15:02 -0600, Albert Hopkins wrote:
    >
    > 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.


    That doesn't follow. The problem is not that x < nan returns False
    because that is correct since x isn't smaller than nan. The problem
    is cmp(x, nan) returning 1, because that indicates that x is greater
    than nan and that isn't true.

    --
    Antoon Pardon
     
    Antoon Pardon, Jan 24, 2008
    #17
  18. Antoon Pardon wrote:
    > That doesn't follow. The problem is not that x < nan returns False
    > because that is correct since x isn't smaller than nan. The problem
    > is cmp(x, nan) returning 1, because that indicates that x is greater
    > than nan and that isn't true.


    Please report the problem. cmp(), min() and max() don't treat NaNs
    right. I don't think that x < nan == False is the correct answer, too.
    But I've to check the IEEE 754 specs. IMHO < nan and > nan should raise
    an exception.

    Christian
     
    Christian Heimes, Jan 24, 2008
    #18
  19. Albert Hopkins

    Paddy Guest

    On Jan 24, 2:28 pm, Christian Heimes <> wrote:
    > Antoon Pardon wrote:
    > > That doesn't follow. The problem is not that x < nan returns False
    > > because that is correct since x isn't smaller than nan. The problem
    > > is cmp(x, nan) returning 1, because that indicates that x is greater
    > > than nan and that isn't true.

    >
    > Please report the problem. cmp(), min() and max() don't treat NaNs
    > right. I don't think that x < nan == False is the correct answer, too.
    > But I've to check the IEEE 754 specs. IMHO < nan and > nan should raise
    > an exception.
    >
    > Christian


    To a floating point interested layman such as I, treating not-a-number
    comparisons with floats should give the same result as comparing a
    fileobject (also not-a-number), with a float. Or does nan have /need a
    more domain specific interpretation?

    - Paddy.
     
    Paddy, Jan 24, 2008
    #19
  20. Albert Hopkins

    Pete Forman Guest

    Christian Heimes <> writes:

    > Antoon Pardon wrote:
    >> That doesn't follow. The problem is not that x < nan returns False
    >> because that is correct since x isn't smaller than nan. The problem
    >> is cmp(x, nan) returning 1, because that indicates that x is greater
    >> than nan and that isn't true.

    >
    > Please report the problem. cmp(), min() and max() don't treat NaNs
    > right. I don't think that x < nan == False is the correct answer, too.
    > But I've to check the IEEE 754 specs. IMHO < nan and > nan should raise
    > an exception.


    I disagree with your last sentence. We are dealing with quiet NaNs
    which should not raise exceptions. x < nan is well defined in IEEE,
    it is false.

    IMHO cmp() should raise an exception if one or more arguments is a
    NaN. Its current definition is to return an integer which may be
    negative, zero, or positive for less than, equal, or greater than.
    There is no spec for unordered, and the integer returned cannot be
    NaN.

    I'd be happy if min() and max() behaved as if their comparison
    operations were minNum and maxNum from IEEE. In other words they
    never return NaN unless all their arguments are NaN.

    int(nan) should raise an exception. I note that in Python 2.5.1
    int(inf) already does.
    --
    Pete Forman -./\.- Disclaimer: This post is originated
    WesternGeco -./\.- by myself and does not represent
    -./\.- the opinion of Schlumberger or
    http://petef.port5.com -./\.- WesternGeco.
     
    Pete Forman, Jan 24, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick

    Max Min

    Patrick, Jul 29, 2004, in forum: VHDL
    Replies:
    1
    Views:
    3,025
    Jonathan Bromley
    Jul 29, 2004
  2. David Frauzel
    Replies:
    1
    Views:
    528
    Steve Grazzini
    Sep 23, 2003
  3. Lois
    Replies:
    1
    Views:
    3,247
    Ryan Stewart
    Dec 27, 2004
  4. juergen
    Replies:
    3
    Views:
    570
    opalinski from opalpaweb
    Sep 20, 2006
  5. carmen

    Converting hrs and min to just min

    carmen, Aug 10, 2004, in forum: ASP General
    Replies:
    4
    Views:
    135
    carmen
    Aug 10, 2004
Loading...

Share This Page