[issue11986] Min/max not symmetric in presence of NaN

Marco Sulla report at bugs.python.org
Mon Dec 23 16:35:06 EST 2019


Marco Sulla <launchpad.net at marco.sulla.e4ward.com> added the comment:

marco at buzz:~$ python3.9
Python 3.9.0a0 (heads/master-dirty:d8ca2354ed, Oct 30 2019, 20:25:01) 
[GCC 9.2.1 20190909] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import Decimal as Dec, BasicContext as Bctx
>>> a = Dec("1981", Bctx)
>>> b = Dec("nan", Bctx)
>>> a.max(b)
Decimal('1981')
>>> b.max(a)
Decimal('1981')
>>> Bctx.max(a, b)
Decimal('1981')
>>> Bctx.max(b, a)
Decimal('1981')


`Decimal` completely adheres to IEEE 754 standard.

There's a very, very simple and generic solution for builtin min and max:



_sentinel = object()

def max(*args, key=None, default=_sentinel):
    args_len = len(args)
    
    if args_len == 0:
        if default is _sentinel:
            fname = max.__name__
            raise ValueError(f"{fname}() expected 1 argument, got 0")
        
        return default
    elif args_len == 1:
        seq = args[0]
    else:
        seq = args
    
    it = iter(seq)
    
    vmax = next(it, _sentinel)
    
    if vmax is _sentinel:
        if default is _sentinel:
            fname = max.__name__
            raise ValueError(f"{fname}() arg is an empty sequence")
        
        return default
    
    
    first_comparable = False
    
    if key is None:
        for val in it:
            if vmax < val:
                vmax = val
                first_comparable = True
            elif not first_comparable and not val < vmax :
                # equal, or not comparable object, like NaN
                vmax = val
    else:
        fmax = key(vmax)
        
        for val in it:
            fval = key(val)
            
            if fmax < fval :
                fmax = fval
                vmax = val
                first_comparable = True
            elif not first_comparable and not fval < fmax:
                fmax = fval
                vmax = val
    
    return vmax


This function continues to give undefined behavior with sets... but who calculates the "maximum" or "minimum" of sets?

----------
nosy: +Marco Sulla

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue11986>
_______________________________________


More information about the Python-bugs-list mailing list