Thread

  1. min() and NaN

    Michael S. Tibbetts <mtibbetts@head-cfa.harvard.edu> — 2003-07-15T19:09:22Z

    Hi,
    
    I have a table containing a double precision column. That column 
    contains at least one judiciously placed NaN.
    
    I'd expect the aggregate function min() to return the minimum, valid 
    numeric value.  Instead, it seems to return the minimum value from the 
    subset of rows following the 'NaN'.
    
    What's going here?  What should I expect the aggregate function min() to 
    return in this case?  And why?
    
    Any help is appreciated,
    Mike
    
    
    testdb=> \d min_with_nan
           Table "public.min_with_nan"
      Column |       Type       | Modifiers
    --------+------------------+-----------
      col1   | double precision |
    
    testdb=> select * from min_with_nan ;
      col1
    -------
      3.141
      2.718
        NaN
         10
    (4 rows)
    
    testdb=> select min(col1) from min_with_nan ;
      min
    -----
       10
    (1 row)
    
    testdb=> select min(col1) from min_with_nan where col1 != 'NaN';
       min
    -------
      2.718
    (1 row)
    
    
    
  2. Re: min() and NaN

    Tom Lane <tgl@sss.pgh.pa.us> — 2003-07-20T04:40:22Z

    "Michael S. Tibbetts" <mtibbetts@head-cfa.cfa.harvard.edu> writes:
    > I'd expect the aggregate function min() to return the minimum, valid 
    > numeric value.  Instead, it seems to return the minimum value from the 
    > subset of rows following the 'NaN'.
    
    Not real surprising given than min() is implemented with float8smaller,
    which does this:
    
    	result = ((arg1 > arg2) ? arg1 : arg2);
    
    In most C implementations, any comparison involving a NaN will return
    "false".  So when we hit the NaN, we have arg1 = min so far, arg2 = NaN,
    comparison yields false, result is NaN.  On the next row, we have
    arg1 = NaN, arg2 = next value, comparison yields false, result is next
    value; and away it goes.
    
    We could probably make it work the way you want with explicit tests for
    NaN in float8smaller, arranged to make sure that the result is not NaN
    unless both inputs are NaN.  But I'm not entirely convinced that we
    should make it work like that.  The other float8 comparison operators
    are designed to treat NaN as larger than every other float8 value (so
    that it has a well-defined position when sorting), and I'm inclined to
    think that float8smaller and float8larger probably should behave
    likewise.  (That actually is the same as what you want for MIN(), but
    not for MAX() ...)
    
    Comments anyone?
    
    			regards, tom lane
    
    
  3. Re: min() and NaN

    Stephan Szabo <sszabo@megazone.bigpanda.com> — 2003-07-20T06:11:34Z

    On Tue, 15 Jul 2003, Michael S. Tibbetts wrote:
    
    > Hi,
    >
    > I have a table containing a double precision column. That column
    > contains at least one judiciously placed NaN.
    >
    > I'd expect the aggregate function min() to return the minimum, valid
    > numeric value.  Instead, it seems to return the minimum value from the
    > subset of rows following the 'NaN'.
    
    This appears to be a bug in the min (and presumably max) aggregate
    function for floats.  AFAICT It should use the same logic as the < (or >)
    comparison operator for the type (SQL92 6.5 GR2b iii I believe), but it's
    just doing a < (or >) in C on the two arguments which isn't the same.
    
    Changing it to follow those rules would give 2.718 for min and it looks
    like NaN for max.
    
    
    
  4. Re: min() and NaN

    Stephan Szabo <sszabo@megazone.bigpanda.com> — 2003-07-20T06:26:28Z

    On Sun, 20 Jul 2003, Tom Lane wrote:
    
    > "Michael S. Tibbetts" <mtibbetts@head-cfa.cfa.harvard.edu> writes:
    > > I'd expect the aggregate function min() to return the minimum, valid
    > > numeric value.  Instead, it seems to return the minimum value from the
    > > subset of rows following the 'NaN'.
    >
    > Not real surprising given than min() is implemented with float8smaller,
    > which does this:
    >
    > 	result = ((arg1 > arg2) ? arg1 : arg2);
    >
    > In most C implementations, any comparison involving a NaN will return
    > "false".  So when we hit the NaN, we have arg1 = min so far, arg2 = NaN,
    > comparison yields false, result is NaN.  On the next row, we have
    > arg1 = NaN, arg2 = next value, comparison yields false, result is next
    > value; and away it goes.
    >
    > We could probably make it work the way you want with explicit tests for
    > NaN in float8smaller, arranged to make sure that the result is not NaN
    > unless both inputs are NaN.  But I'm not entirely convinced that we
    > should make it work like that.  The other float8 comparison operators
    > are designed to treat NaN as larger than every other float8 value (so
    > that it has a well-defined position when sorting), and I'm inclined to
    > think that float8smaller and float8larger probably should behave
    > likewise.  (That actually is the same as what you want for MIN(), but
    > not for MAX() ...)
    
    The spec seems to say that min/max should work the same way as the
    comparison operators by saying that it returns the maximum or minimum
    value as determined by the comparison rules of the comparison predicate
    section.  That'd seem to be asking for the second version.
    
    
    
  5. Re: min() and NaN

    Jean-Luc Lachance <jllachan@nsd.ca> — 2003-07-21T15:41:43Z

    If a compare with NaN is always false, how about rewriting it as:
    result = ((arg1 < arg2) ? arg2 : arg1).
    
    Or better yet, swap arg1 and arg2 when calling float8smaller.
    Use flaost8smaller( current_min, value).
    
    JLL
    
    Tom Lane wrote:
    > 
    > "Michael S. Tibbetts" <mtibbetts@head-cfa.cfa.harvard.edu> writes:
    > > I'd expect the aggregate function min() to return the minimum, valid
    > > numeric value.  Instead, it seems to return the minimum value from the
    > > subset of rows following the 'NaN'.
    > 
    > Not real surprising given than min() is implemented with float8smaller,
    > which does this:
    > 
    >         result = ((arg1 > arg2) ? arg1 : arg2);
    > 
    > In most C implementations, any comparison involving a NaN will return
    > "false".  So when we hit the NaN, we have arg1 = min so far, arg2 = NaN,
    > comparison yields false, result is NaN.  On the next row, we have
    > arg1 = NaN, arg2 = next value, comparison yields false, result is next
    > value; and away it goes.
    > 
    > We could probably make it work the way you want with explicit tests for
    > NaN in float8smaller, arranged to make sure that the result is not NaN
    > unless both inputs are NaN.  But I'm not entirely convinced that we
    > should make it work like that.  The other float8 comparison operators
    > are designed to treat NaN as larger than every other float8 value (so
    > that it has a well-defined position when sorting), and I'm inclined to
    > think that float8smaller and float8larger probably should behave
    > likewise.  (That actually is the same as what you want for MIN(), but
    > not for MAX() ...)
    > 
    > Comments anyone?
    > 
    >                         regards, tom lane
    > 
    > ---------------------------(end of broadcast)---------------------------
    > TIP 3: if posting/reading through Usenet, please send an appropriate
    >       subscribe-nomail command to majordomo@postgresql.org so that your
    >       message can get through to the mailing list cleanly
    
    
  6. Re: min() and NaN

    Tom Lane <tgl@sss.pgh.pa.us> — 2003-07-21T15:43:19Z

    Jean-Luc Lachance <jllachan@nsd.ca> writes:
    > If a compare with NaN is always false, how about rewriting it as:
    > result = ((arg1 < arg2) ? arg2 : arg1).
    
    That just changes the failure mode.
    
    			regards, tom lane
    
    
  7. Re: min() and NaN

    Bruce Momjian <pgman@candle.pha.pa.us> — 2003-07-22T01:34:43Z

    Is this a TODO?
    
    ---------------------------------------------------------------------------
    
    Tom Lane wrote:
    > Jean-Luc Lachance <jllachan@nsd.ca> writes:
    > > If a compare with NaN is always false, how about rewriting it as:
    > > result = ((arg1 < arg2) ? arg2 : arg1).
    > 
    > That just changes the failure mode.
    > 
    > 			regards, tom lane
    > 
    > ---------------------------(end of broadcast)---------------------------
    > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
    > 
    
    -- 
      Bruce Momjian                        |  http://candle.pha.pa.us
      pgman@candle.pha.pa.us               |  (610) 359-1001
      +  If your life is a hard drive,     |  13 Roberts Road
      +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
    
    
  8. Re: min() and NaN

    Tom Lane <tgl@sss.pgh.pa.us> — 2003-07-22T06:09:09Z

    Bruce Momjian <pgman@candle.pha.pa.us> writes:
    > Is this a TODO?
    
    It'll only take ten minutes to make it a DONE, once we figure out what
    the behavior ought to be.  So far I think both Stephan and I argued that
    MIN/MAX ought to treat NaN as larger than all ordinary values, for
    consistency with the comparison operators.  That was not the behavior
    Michael wanted, but I don't see that we have much choice given the
    wording of the SQL spec.  Does anyone want to argue against that
    definition?
    
    			regards, tom lane
    
    
  9. Re: min() and NaN

    Bruce Momjian <pgman@candle.pha.pa.us> — 2003-07-22T16:14:41Z

    Well, my 2 cents is that though we consider NULL when ordering via ORDER
    BY, we ignore it in MAX because it really isn't a value, and NaN seems
    to be similar to NULL.
    
    When doing ORDER BY, we have to put the NULL value somewhere, so we put
    it at the end, but with aggregates, we aren't required to put the NULL
    somewhere, so we ignore it.  Should that be the same for NaN?  I just
    don't see how we can arbitrarly say it is greater/less than other
    values.
    
    ---------------------------------------------------------------------------
    
    Tom Lane wrote:
    > Bruce Momjian <pgman@candle.pha.pa.us> writes:
    > > Is this a TODO?
    > 
    > It'll only take ten minutes to make it a DONE, once we figure out what
    > the behavior ought to be.  So far I think both Stephan and I argued that
    > MIN/MAX ought to treat NaN as larger than all ordinary values, for
    > consistency with the comparison operators.  That was not the behavior
    > Michael wanted, but I don't see that we have much choice given the
    > wording of the SQL spec.  Does anyone want to argue against that
    > definition?
    > 
    > 			regards, tom lane
    > 
    > ---------------------------(end of broadcast)---------------------------
    > TIP 2: you can get off all lists at once with the unregister command
    >     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
    > 
    
    -- 
      Bruce Momjian                        |  http://candle.pha.pa.us
      pgman@candle.pha.pa.us               |  (610) 359-1001
      +  If your life is a hard drive,     |  13 Roberts Road
      +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
    
    
  10. Re: min() and NaN

    Stephan Szabo <sszabo@megazone.bigpanda.com> — 2003-07-22T18:32:36Z

    On Tue, 22 Jul 2003, Bruce Momjian wrote:
    
    > Well, my 2 cents is that though we consider NULL when ordering via ORDER
    > BY, we ignore it in MAX because it really isn't a value, and NaN seems
    > to be similar to NULL.
    >
    > When doing ORDER BY, we have to put the NULL value somewhere, so we put
    > it at the end, but with aggregates, we aren't required to put the NULL
    > somewhere, so we ignore it.  Should that be the same for NaN?  I just
    > don't see how we can arbitrarly say it is greater/less than other
    > values.
    
    But we already do. When doing a less than/greater than comparison, 'NaN'
    is considered greater than normal values which is different from NULL
    which returns unknown for both.
    
    
    
  11. Re: min() and NaN

    Jean-Luc Lachance <jllachan@nsd.ca> — 2003-07-22T18:50:11Z

    Hey! here is a (stupid maybe) idea.  Why not disallow 'NaN' for a float?
    
    JLL
    
    
    
    
    Stephan Szabo wrote:
    > 
    > On Tue, 22 Jul 2003, Bruce Momjian wrote:
    > 
    > > Well, my 2 cents is that though we consider NULL when ordering via ORDER
    > > BY, we ignore it in MAX because it really isn't a value, and NaN seems
    > > to be similar to NULL.
    > >
    > > When doing ORDER BY, we have to put the NULL value somewhere, so we put
    > > it at the end, but with aggregates, we aren't required to put the NULL
    > > somewhere, so we ignore it.  Should that be the same for NaN?  I just
    > > don't see how we can arbitrarly say it is greater/less than other
    > > values.
    > 
    > But we already do. When doing a less than/greater than comparison, 'NaN'
    > is considered greater than normal values which is different from NULL
    > which returns unknown for both.
    
    
  12. Re: min() and NaN

    Bruce Momjian <pgman@candle.pha.pa.us> — 2003-07-22T18:59:19Z

    Stephan Szabo wrote:
    > 
    > On Tue, 22 Jul 2003, Bruce Momjian wrote:
    > 
    > > Well, my 2 cents is that though we consider NULL when ordering via ORDER
    > > BY, we ignore it in MAX because it really isn't a value, and NaN seems
    > > to be similar to NULL.
    > >
    > > When doing ORDER BY, we have to put the NULL value somewhere, so we put
    > > it at the end, but with aggregates, we aren't required to put the NULL
    > > somewhere, so we ignore it.  Should that be the same for NaN?  I just
    > > don't see how we can arbitrarly say it is greater/less than other
    > > values.
    > 
    > But we already do. When doing a less than/greater than comparison, 'NaN'
    > is considered greater than normal values which is different from NULL
    > which returns unknown for both.
    
    But maybe that logic is the same as ORDER BY, where we have to give it
    some location in sorting order, while with aggregates we don't.
    
    I am not strong on this, but just point it out.
    
    -- 
      Bruce Momjian                        |  http://candle.pha.pa.us
      pgman@candle.pha.pa.us               |  (610) 359-1001
      +  If your life is a hard drive,     |  13 Roberts Road
      +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
    
    
  13. Re: min() and NaN

    Tom Lane <tgl@sss.pgh.pa.us> — 2003-07-22T19:33:19Z

    Bruce Momjian <pgman@candle.pha.pa.us> writes:
    > Well, my 2 cents is that though we consider NULL when ordering via ORDER
    > BY, we ignore it in MAX because it really isn't a value, and NaN seems
    > to be similar to NULL.
    
    Good idea, but I don't think we can get away with it.  The spec says
    that MAX/MIN have to be consistent with the comparison operators (and
    therefore with ORDER BY):
    
                iii) If MAX or MIN is specified, then the result is respec-
                     tively the maximum or minimum value in TXA. These results
                     are determined using the comparison rules specified in
                     Subclause 8.2, "<comparison predicate>".
    
    NULL can be special, because it acts specially in comparisons anyway.
    But NaN is just a value of the datatype.
    
    I'd be willing to go against the spec if I thought that having
    ignore-NaNs behavior was sufficiently important, but I don't think it's
    important enough to disregard the spec...
    
    			regards, tom lane
    
    
  14. Re: min() and NaN

    Bruce Momjian <pgman@candle.pha.pa.us> — 2003-07-22T20:19:57Z

    Tom Lane wrote:
    > Bruce Momjian <pgman@candle.pha.pa.us> writes:
    > > Well, my 2 cents is that though we consider NULL when ordering via ORDER
    > > BY, we ignore it in MAX because it really isn't a value, and NaN seems
    > > to be similar to NULL.
    > 
    > Good idea, but I don't think we can get away with it.  The spec says
    > that MAX/MIN have to be consistent with the comparison operators (and
    > therefore with ORDER BY):
    > 
    >             iii) If MAX or MIN is specified, then the result is respec-
    >                  tively the maximum or minimum value in TXA. These results
    >                  are determined using the comparison rules specified in
    >                  Subclause 8.2, "<comparison predicate>".
    > 
    > NULL can be special, because it acts specially in comparisons anyway.
    > But NaN is just a value of the datatype.
    > 
    > I'd be willing to go against the spec if I thought that having
    > ignore-NaNs behavior was sufficiently important, but I don't think it's
    > important enough to disregard the spec...
    
    Yep.
    
    -- 
      Bruce Momjian                        |  http://candle.pha.pa.us
      pgman@candle.pha.pa.us               |  (610) 359-1001
      +  If your life is a hard drive,     |  13 Roberts Road
      +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
    
    
  15. Re: min() and NaN

    Greg Stark <gsstark@mit.edu> — 2003-07-24T18:35:46Z

    Tom Lane <tgl@sss.pgh.pa.us> writes:
    
    > NULL can be special, because it acts specially in comparisons anyway.
    > But NaN is just a value of the datatype.
    
    Does postgres intend to support all the different types of NaN? Does you
    intend to have +Inf and -Inf and underflow detection and all the other goodies
    you actually need to make it useful?
    
    If not it seems more useful to just use the handy unknown-value thing SQL
    already has and turn NaN into a NULL. 
    
    -- 
    greg
    
    
    
  16. Re: min() and NaN

    Tom Lane <tgl@sss.pgh.pa.us> — 2003-07-24T18:44:10Z

    Greg Stark <gsstark@mit.edu> writes:
    > Does postgres intend to support all the different types of NaN? Does you
    > intend to have +Inf and -Inf and underflow detection and all the other goodies
    > you actually need to make it useful?
    
    We have some of that; it needs work, and it's always going to be
    dependent on the platform having proper IEEE support, but that's no
    excuse to throw it away.
    
    			regards, tom lane