On Mon, Aug 30, 2021 at 1:33 PM Steven D'Aprano <st...@pearwood.info> wrote:
> However we could add a function, totalorder, which can be used as a key
> function to force an order on NANs. The 2008 version of the IEEE-754
> standard recommends such a function:
>
>     from some_module import totalorder
>     sorted([4, nan, 2, 5, 1, nan, 3, 0], key=totalorder)
>     # --> [nan, nan, 0, 1, 2, 3, 4, 5]
>
> It would be nice if such a totalorder function worked correctly on both
> floats and Decimals. Anyone feel up to writing one?
>

I really don't feel like buying the standards document itself, so I'm
going based on this, which appears to be quoting the standard:

https://github.com/rust-lang/rust/issues/5585

Based on that, I don't think it's possible to have a totalorder
function that will work 100% correctly on float and Decimal in a
mixture. I suspect it's not even possible to make it generic while
still being fully compliant.

The differences from the vanilla less-than operator are:

1) Positive zero sorts after negative zero
2) NaNs sort at one end or the other depending on their sign bit
3) Signalling NaNs are closer to zero than quiet
4) NaNs are sorted by payload
5) Different representations of the same value are distinguished by
their exponents. I'm not sure when that would come up.

So here are two partial implementations.

1) Ensure that NaNs are at the end, but otherwise unchanged.
Compatible with all numeric types.

def simpleorder(val): return (val != val, val)

2) Acknowledge signs on NaNs and zeroes. Compatible with floats, not
sure about Decimals. I haven't figured out how to make a negative NaN
in Decimal.

def floatorder(val): return (math.copysign(1, val), val != val, val)

Neither is fully compliant. A signalling NaN will probably cause an
error. (I have no idea. Never worked with them.) NaN payloads... I
don't know how to access those in Python other than with ctypes. And
if two floats represent the same number, under what circumstances
could their exponents differ?

I doubt we'll get a fully compliant implementation in Python. If one
is to exist, it'd probably be best to write it in C, using someone
else's code:

https://www.gnu.org/software/libc/manual/html_node/FP-Comparison-Functions.html

And it would be specific to float, not Decimal, which would need a
completely different implementation. I'm not sure how many of the same
concepts even exist.

TBH, I would just use simpleorder for most situations. It's simple,
easy, and doesn't care about data types. All NaNs get shoved to the
end, everything else gets compared normally.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@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/UYJH4XECKZQGOZMDLMJKPZRRNFV67PDT/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to