Re: NaN comparisons - Call For Anecdotes

2014-07-18 Thread Steven D'Aprano
On Fri, 18 Jul 2014 01:36:24 +1000, Chris Angelico wrote:

 On Fri, Jul 18, 2014 at 1:12 AM, Johann Hibschman jhibsch...@gmail.com
 wrote:
 Well, I just spotted this thread.  An easy example is, well, pretty
 much any case where SQL NULL would be useful.  Say I have lists of
 borrowers, the amount owed, and the amount they paid so far.

 nan = float(nan)
 borrowers = [Alice, Bob, Clem, Dan] amount_owed = [100.0,
 nan, 200.0, 300.0] amount_paid = [100.0, nan, nan, 200.0]
 who_paid_off = [b for (b, ao, ap) in
   zip(borrowers, amount_owed, amount_paid)
   if ao == ap]

 I want to just get Alice from that list, not Bob.  I don't know how
 much Bow owes or how much he's paid, so I certainly don't know that
 he's paid off his loan.


 But you also don't know that he hasn't. NaN doesn't mean unknown, it
 means Not a Number. You need a more sophisticated system that allows
 for uncertainty in your data. I would advise using either None or a
 dedicated singleton (something like `unknown = object()` would work, or
 you could make a custom type with a more useful repr)

Hmmm, there's something to what you say there, but IEEE-754 NANs seem to 
have been designed to do quadruple (at least!) duty with multiple 
meanings, including:

- Missing values (I took a reading, but I can't read my handwriting).

- Data known only qualitatively, not quantitatively (e.g. windspeed =
  fearsome).

- Inapplicable values, e.g. the average depth of the oceans on Mars.

- The result of calculations which are mathematically indeterminate,
  such as 0/0.

- The result of real-valued calculations which are invalid due to
  domain errors, such as sqrt(-1) or acos(2.5).

- The result of calculations which are conceptually valid, but are
  unknown due to limitations of floats, e.g. you have two finite
  quantities which have both overflowed to INF, the difference
  between them ought to be finite, but there's no way to tell what
  it should be.


It seems to me that the way you treat a NAN will often depend on which 
category it falls under. E.g. when taking the average of a set of values, 
missing values ought to be skipped over, while actual indeterminate NANs 
ought to carry through:

average([1, 1, 1, Missing, 1]) = 1
average([1, 1, 1, 0/0, 1]) = NAN

I know that R distinguishes between NA and IEEE-754 NANs, although I'm 
not sure how complete its support for NANs is. But many (most?) R 
functions take an argument controlling whether or not to ignore NA values.

In principle, you can encode the different meanings into NANs using the 
payload. There are 9007199254740988 possible Python float NANs. Half of 
these are signalling NANs, half are quiet NANs. Ignoring the sign bit 
leaves us with 2251799813685247 distinct sNANs and the same qNANs. That's 
enough to encode a *lot* of different meanings.

[Aside: I find myself perplexed why IEEE-754 says that the sign bit of 
NANs should be ignored, but then specifies that another bit is to be used 
to distinguish signalling from quiet NANs. Why not just interpret NANs 
with the sign bit set are signalling, those with it clear are quiet?]



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-18 Thread Chris Angelico
On Sat, Jul 19, 2014 at 3:57 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 Hmmm, there's something to what you say there, but IEEE-754 NANs seem to
 have been designed to do quadruple (at least!) duty with multiple
 meanings, including:

 - Missing values (I took a reading, but I can't read my handwriting).

 - Data known only qualitatively, not quantitatively (e.g. windspeed =
   fearsome).

 - Inapplicable values, e.g. the average depth of the oceans on Mars.

 - The result of calculations which are mathematically indeterminate,
   such as 0/0.

 - The result of real-valued calculations which are invalid due to
   domain errors, such as sqrt(-1) or acos(2.5).

 - The result of calculations which are conceptually valid, but are
   unknown due to limitations of floats, e.g. you have two finite
   quantities which have both overflowed to INF, the difference
   between them ought to be finite, but there's no way to tell what
   it should be.

Huh, okay. I thought the definition of NaN was based on the fourth one
(mathematically indeterminate) and then it logically accepted the
subsequent two (sqrt(-1) IMO is better handled by either a complex
number or a thrown error, but NaN does make some sense there;
definitely inf-inf = nan is as logical as 0/0 = nan). The first two
seem to be better handled by SQL's NULL value (or non-value, or
something, or maybe not something); the third is a bit trickier.
Although the average of no values is logically calculated as 0/0
(ergo NaN makes sense there), I would say NaN isn't really right for a
truly inapplicable value - for instance, recording the mass of a
non-physical object. In an inventory system, it's probably simplest to
use 0.0 to mean non-physical item, but it might be worth
distinguishing between physical item with sufficiently low mass that
it underflows our measurements (like a single sheet of paper when
you're working with postal scales) and non-physical item with no
meaningful mass (like credit card fees). In that case, I'm not sure
that NaN is really appropriate to the situation, but would defer to
IEE 754 on the subject.

Obviously it's possible to abuse anything to mean anything (I do
remember using nullable fields in DB2 to mean everything from inherit
this value from parent to here be magic, code will work out the real
value on the fly), but this is a question of intent and good design.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Johann Hibschman
Anders J. Munch 2...@jmunch.dk writes:
 So far I received exactly the answer I was expecting.  0 examples of
 NaN!=NaN being beneficial.
 I wasn't asking for help, I was making a point.  Whether that will
 lead to improvement of Python, well, I'm not too optimistic, but I
 feel the point was worth making regardless.

Well, I just spotted this thread.  An easy example is, well, pretty much
any case where SQL NULL would be useful.  Say I have lists of borrowers,
the amount owed, and the amount they paid so far.

nan = float(nan)
borrowers = [Alice, Bob, Clem, Dan]
amount_owed = [100.0, nan, 200.0, 300.0]
amount_paid = [100.0, nan, nan, 200.0]
who_paid_off = [b for (b, ao, ap) in
  zip(borrowers, amount_owed, amount_paid)
  if ao == ap]

I want to just get Alice from that list, not Bob.  I don't know how much
Bow owes or how much he's paid, so I certainly don't know that he's paid
off his loan.

Cheers,
Johann
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Chris Angelico
On Fri, Jul 18, 2014 at 1:12 AM, Johann Hibschman jhibsch...@gmail.com wrote:
 Well, I just spotted this thread.  An easy example is, well, pretty much
 any case where SQL NULL would be useful.  Say I have lists of borrowers,
 the amount owed, and the amount they paid so far.

 nan = float(nan)
 borrowers = [Alice, Bob, Clem, Dan]
 amount_owed = [100.0, nan, 200.0, 300.0]
 amount_paid = [100.0, nan, nan, 200.0]
 who_paid_off = [b for (b, ao, ap) in
   zip(borrowers, amount_owed, amount_paid)
   if ao == ap]

 I want to just get Alice from that list, not Bob.  I don't know how much
 Bow owes or how much he's paid, so I certainly don't know that he's paid
 off his loan.


But you also don't know that he hasn't. NaN doesn't mean unknown, it
means Not a Number. You need a more sophisticated system that allows
for uncertainty in your data. I would advise using either None or a
dedicated singleton (something like `unknown = object()` would work,
or you could make a custom type with a more useful repr), and probably
checking for it explicitly. It's entirely possible that you do
virtually identical (or virtually converse) checks but with different
handling of unknowns - for instance, you might have one check for who
should be sent a loan reminder letter in which you leave out all
unknowns, and another check for which accounts should be flagged for
human checking in which you keep the unknowns (and maybe ignore every
loan 100.0). You have a special business case here (the need to
record information with a maybe state), and you need to cope with
it, which means dedicated logic and planning and design and code.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Johann Hibschman
Chris Angelico ros...@gmail.com writes:

 But you also don't know that he hasn't. NaN doesn't mean unknown, it
 means Not a Number. You need a more sophisticated system that allows
 for uncertainty in your data.

Regardless of whether this is the right design, it's still an example of
use.

As to the design, using NaN to implement NA is a hack with a long
history, see

  http://www.numpy.org/NA-overview.html

for some color.  Using NaN gets us a hardware-accelerated implementation
with just about the right semantics.  In a real example, these lists are
numpy arrays with tens of millions of elements, so this isn't a trivial
benefit.  (Technically, that's what's in the database; a given analysis
may look at a sample of 100k or so.)

 You have a special business case here (the need to
 record information with a maybe state), and you need to cope with
 it, which means dedicated logic and planning and design and code.

Yes, in principle.  In practice, everyone is used to the semantics of
R-style missing data, which are reasonably well-matched by nan.  In
principle, (NA == 1.0) should be a NA (missing) truth value, as should
(NA == NA), but in practice having it be False is more useful.  As an
example, indexing R vectors by a boolean vector containing NA yields NA
results, which is a feature that I never want.

Cheers,
Johann
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Chris Angelico
On Fri, Jul 18, 2014 at 4:49 AM, Johann Hibschman jhibsch...@gmail.com wrote:
 Chris Angelico ros...@gmail.com writes:

 But you also don't know that he hasn't. NaN doesn't mean unknown, it
 means Not a Number. You need a more sophisticated system that allows
 for uncertainty in your data.

 Regardless of whether this is the right design, it's still an example of
 use.

Sure it is. And you may well have earned yourself that beer. But I
don't put too much stock in hacks, at least as regards design
decisions elsewhere. It's a little dubious when you grant special
meaning to things and then use that meaning to justify the things'
semantics. I'd much rather find an example where, for instance,
numerical calculations might overflow to +inf or -inf, and then
further calculations can result in a nan, etc, etc. Those are the
sorts of examples that you'd find among SciPy users and such.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Chris Angelico
On Fri, Jul 18, 2014 at 4:49 AM, Johann Hibschman jhibsch...@gmail.com wrote:
 In
 principle, (NA == 1.0) should be a NA (missing) truth value, as should
 (NA == NA), but in practice having it be False is more useful.

This is actually fairly easily implemented, if you ever want it.

class NAType:
def __repr__(self): return NA
def __eq__(self, other): return self
__lt__ = __gt__ = __le__ = __ge__ = __ne__ = __eq__
NA = NAType()

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Marko Rauhamaa
Chris Angelico ros...@gmail.com:

 numerical calculations might overflow to +inf or -inf, and then
 further calculations can result in a nan, etc, etc. Those are the
 sorts of examples that you'd find among SciPy users and such.

There is some inconsistency.

Mathematically, there are undefined operations, for a good reason.
That's because the limits are not unambiguous and that's why 0/0, 0**0,
1/0 and inf-inf are undefined.

Why 0/0 results in an exception but inf-inf = nan, I don't see a
justification.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Ian Kelly
On Thu, Jul 17, 2014 at 1:10 PM, Marko Rauhamaa ma...@pacujo.net wrote:
 Mathematically, there are undefined operations, for a good reason.
 That's because the limits are not unambiguous and that's why 0/0, 0**0,
 1/0 and inf-inf are undefined.

Well, 0**0 is usually defined as 1, despite the limits being
ambiguous.  Also, 1/0 in IEEE 754 is defined as inf.

 Why 0/0 results in an exception but inf-inf = nan, I don't see a
 justification.

I expect that float division by zero was made to raise an exception
for consistency with integer division by zero, where it might be
considered inappropriate to switch types and return inf or nan.
Granted that nowadays integer division returns a float anyway, but
there is still floor division to think about. Maybe this should have
been fixed in Python 3, but it wasn't.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Marko Rauhamaa
Ian Kelly ian.g.ke...@gmail.com:

 Well, 0**0 is usually defined as 1, despite the limits being
 ambiguous.

URL: https://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml

But if it could be defined, what should it be? 0 or 1? 


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Ian Kelly
On Thu, Jul 17, 2014 at 3:08 PM, Marko Rauhamaa ma...@pacujo.net wrote:
 Ian Kelly ian.g.ke...@gmail.com:

 Well, 0**0 is usually defined as 1, despite the limits being
 ambiguous.

 URL: https://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml

 But if it could be defined, what should it be? 0 or 1?

I did say usually. There's not one single Holy Keeper of the
Definitions for mathematics. Wikipedia lists some differing opinions
on the subject:

http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_power_of_zero

I note that mathworld.wolfram.com also lists it as undefined, though.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-17 Thread Ian Kelly
On Thu, Jul 17, 2014 at 5:00 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Thu, Jul 17, 2014 at 3:08 PM, Marko Rauhamaa ma...@pacujo.net wrote:
 Ian Kelly ian.g.ke...@gmail.com:

 Well, 0**0 is usually defined as 1, despite the limits being
 ambiguous.

 URL: https://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml

 But if it could be defined, what should it be? 0 or 1?

 I did say usually. There's not one single Holy Keeper of the
 Definitions for mathematics. Wikipedia lists some differing opinions
 on the subject:

 http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_power_of_zero

 I note that mathworld.wolfram.com also lists it as undefined, though.

Incidentally, as noted in the Wikipedia article you left out some
options -- it's not just between 0 or 1. It's also possible to derive
a limit of positive infinity or any nonnegative real.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-15 Thread Anders J. Munch

Steven D'Aprano:

I'll give you the benefit of the doubt, and assume that when you first
posted you hadn't realised that the audience here does not have the
relevant experience, but by refusing to ask the question elsewhere, and
by making snide comments that they don't like beer, that pretty much
gives the game away that you're looking to have your opinion confirmed
rather than looking for an honest answer.


I really did run out of time when I said I did: I spent the last 5 days running 
a chess tournament with 137 participants, with the tournament management 
software written in Python by yours truly. Which worked beautifully, Python is a 
great language. And I'm going to Iceland on vacation tomorrow, so I'm not going 
to start a new discussion of a different mailing list just now, maybe later. Not 
everyone is as prolific a writer as you are, Steven.


The talk about the wrong list would have carried more weight if you had 
started out by saying wrong list, instead of going through every other 
argument first, before punting like that. By the way, which list is the 
appropriate one? The numpy and SciPy mailing lists are first and foremost about 
numpy and SciPy, I presume. Is there a general numerics-list somewhere also? I 
don't see any on https://mail.python.org/mailman/listinfo.


By the way, you guys seem to have overlooked the opportunity for arbitrage: 
*Anyone* can go to a numerical list, poll for examples, and come back and earn 
some beer :)


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-15 Thread Mark Lawrence

On 15/07/2014 13:32, Anders J. Munch wrote:


By the way, which list
is the appropriate one? The numpy and SciPy mailing lists are first and
foremost about numpy and SciPy, I presume. Is there a general
numerics-list somewhere also? I don't see any on
https://mail.python.org/mailman/listinfo.



Try here http://news.gmane.org/index.php?prefix=gmane.comp.python

--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-14 Thread Anders J. Munch

alister wrote:

I don't have time to start this discussion over again on another mailing
list.
Don't anyone on those lists read python-list also?

they possibly do, but prefer to keep discussions to the proper forum


The semantics of the Python programming language is on-topic for python-list. 
This is about float.__eq__, not about numpy or SciPy.

Maybe they just don't like beer?

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-14 Thread Mark Lawrence

On 14/07/2014 17:44, Anders J. Munch wrote:

alister wrote:

I don't have time to start this discussion over again on another mailing
list.
Don't anyone on those lists read python-list also?

they possibly do, but prefer to keep discussions to the proper forum


The semantics of the Python programming language is on-topic for
python-list. This is about float.__eq__, not about numpy or SciPy.
Maybe they just don't like beer?

regards, Anders



Maybe they recognise the eqivalent of our resident unicode expert.

--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-14 Thread Ian Kelly
On Mon, Jul 14, 2014 at 10:44 AM, Anders J. Munch 2...@jmunch.dk wrote:
 alister wrote:

 I don't have time to start this discussion over again on another mailing
 list.
 Don't anyone on those lists read python-list also?

 they possibly do, but prefer to keep discussions to the proper forum


 The semantics of the Python programming language is on-topic for
 python-list. This is about float.__eq__, not about numpy or SciPy.
 Maybe they just don't like beer?

Well, I don't see anybody with numerical expertise chiming in here to
say they agree with you either, so that tells me you've probably got
the wrong audience.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-14 Thread Steven D'Aprano
On Mon, 14 Jul 2014 18:44:15 +0200, Anders J. Munch wrote:

 alister wrote:
 I don't have time to start this discussion over again on another
 mailing list.
 Don't anyone on those lists read python-list also?

 they possibly do, but prefer to keep discussions to the proper forum
 
 The semantics of the Python programming language is on-topic for
 python-list. This is about float.__eq__, not about numpy or SciPy. Maybe
 they just don't like beer?

It's about NAN != NAN. The heaviest uses of NANs are numpy and scipy 
users.

You remind me of the proverbial drunk who lost his keys in the park, but 
looks for them in the street under the street light because that's where 
the light is. That's assuming that you actually want an honest answer to 
your question.

If you wanted to learn about use-cases for NANs, you ought to ask 
somewhere where there was a high proportion of numeric programmers, not 
on some list merely because it was convenient.

I'll give you the benefit of the doubt, and assume that when you first 
posted you hadn't realised that the audience here does not have the 
relevant experience, but by refusing to ask the question elsewhere, and 
by making snide comments that they don't like beer, that pretty much 
gives the game away that you're looking to have your opinion confirmed 
rather than looking for an honest answer.


-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-10 Thread alister
On Wed, 09 Jul 2014 23:09:36 +0200, Anders J. Munch wrote:

 Ethan Furman:
 I would suggest you ask for this on the numerical mailing lists instead
 of here -- and you may not want to offer a beer to everyone that has an
 anecdote for NaN behavior being useful.
 I don't have time to start this discussion over again on another mailing
 list.
 Don't anyone on those lists read python-list also?
 
 regards, Anders

they possibly do, but prefer to keep discussions to the proper forum



-- 
If you are going to walk on thin ice, you may as well dance.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-10 Thread MRAB

On 2014-07-10 01:57, Ben Finney wrote:

Anders J. Munch 2...@jmunch.dk writes:


Joel Goldstick wrote:
 I've been following along here, and it seems you haven't received
 the answer you want or need.

So far I received exactly the answer I was expecting. 0 examples of
NaN!=NaN being beneficial.


Predictability and ease of diagnosis are the principles at work
URL:http://stackoverflow.com/a/1573715/70157. You have already
received examples of those.

If those don't convince you of its usefulness, that's unfortunate, but
at this point you are demonstrating a standard which is both
unreasonably high (even the rationale of the committee doesn't convince
you) and unreasonably low (you ask not for explanations but personal
anecdotes).

Good luck to you in your quest.


I can think of one place where equality of NaNs would be useful:
sorting.

However, in that use-case, you would also want it to be orderable,
perhaps greater than any other non-NaN float.

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-10 Thread Chris Angelico
On Thu, Jul 10, 2014 at 9:28 PM, MRAB pyt...@mrabarnett.plus.com wrote:
 I can think of one place where equality of NaNs would be useful:
 sorting.

 However, in that use-case, you would also want it to be orderable,
 perhaps greater than any other non-NaN float.

In that case, you're setting special rules, so you probably want a
key-based sort. Since the sorting of tuples works by comparing
elements sequentially, it's simple enough:

 l=[1.0,2.0,1.5,float(nan),1.7]
 sorted(l,key=lambda n: (n!=n, n))
[1.0, 1.5, 1.7, 2.0, nan]

I'm not sure what's supposed to happen if you just let sorted() go
with its default comparisons. It seems to put the nan at the end, but
I wouldn't bet on that being reliable, unless it's documented
somewhere. Of course, with a key sort you can choose to put NaNs at
the beginning just as easily:

 sorted(l,key=lambda n: (n==n, n))
[nan, 1.0, 1.5, 1.7, 2.0]

You want custom rules for sorting? You got 'em.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Steven D'Aprano
On Wed, 09 Jul 2014 00:57:03 -0400, Terry Reedy wrote:

 On 7/8/2014 8:10 PM, Steven D'Aprano wrote:
 
 There's no force of law that requires Python to enforce reflexivity on
 values where reflexivity does not apply,
 
 There are laws of logic that make the lack of reflexivity obnoxious when
 putting objects in collections. 

Floating point numbers are not real numbers and do not obey the laws of 
real arithmetic. Once you allow floats, or comparisons between arbitrary 
types, no matter what you do, something is going to break and somebody is 
going to be upset.


 Python evaded the problem, at least for
 some builtins, by contradicting itself and treating nans as equal to
 themselves in the context of collections.

It's not just NANs. It's any non-reflexive type:

py class AlwaysUnequal:
... def __eq__(self, other): return False
... 
py x = AlwaysUnequal()
py x in [1, 2, x]
True
py any(x == a for a in [1, 2, x])
False




 In 2.x, 'in' was defined in terms of ==, but
   nan=float('nan')
   nl = [nan]
   nan in nl
 True
 even though nan != the only member of nl.
 
 In 3.x, 'in' was redefined to include 'is' as well as '=='.

I don't understand this. You've just shown an example from Python 2 where 
'in' uses 'is'. How is that a Python 3 change?


-- 
Steve
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Chris Angelico
On Wed, Jul 9, 2014 at 4:43 PM, Steven D'Aprano st...@pearwood.info wrote:
 I don't understand this. You've just shown an example from Python 2 where
 'in' uses 'is'. How is that a Python 3 change?

A docs change.

https://docs.python.org/2/reference/expressions.html#not-in

For the list and tuple types, x in y is true if and only if there
exists an index i such that x == y[i] is true.


https://docs.python.org/3/reference/expressions.html#not-in

For container types such as list, tuple, set, frozenset, dict, or
collections.deque, the expression x in y is equivalent to any(x is e
or x == e for e in y).


So the definition of the operator (as stated in the docs) has changed
to match its behaviour. That's definitely a change; the Py2 behaviour
is buggy according to its docs. Should the Py2 docs be updated to
match the Py3 docs, or should it be left as a minor technical
distinction that almost never is important?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

I wrote:

| class Monitor(Thread):
| def run(self):
| old = self.get_current_value()
| while not self.Terminated:
| new = self.get_current_value()
| if new != old:
| print(time.asctime(), changed to, new)
| old = new
| time.sleep(1)



Huh, I don't know what happened to the identation here, I'l try again:

class Monitor(Thread):
def run(self):
old = self.get_current_value()
while not self.Terminated:
new = self.get_current_value()
if new != old:
print(time.asctime(), changed to, new)
old = new
time.sleep(1)

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

Steven D'Aprano wrote:

It seems to me that the trivial work-around is:

* gather packed floats from some device, as ints
* process them *as ints* in some way which requires reflexivity
* unpack back into floats
* (maybe) much later perform numeric calculations on them


Although perhaps I don't understand your use-case.


Clearly you do not. floats are not ints. I have no idea how you imagine 
processing IEEE-754 floating-point values in int form.


My use case is: Working with IEEE-754 floating-point values. That means storing 
and retrieving them, serialising and transferring them, accepting them as user 
input, printing them, all the usual things you do with values.


And doing so in a way that does not require special handling in algorithms that 
are otherwise generic.
When the same algorithm is capable of dealing with ints, bytestrings, text 
string, tuples, list, dictionaries, time stamps, NoneType's, bools, 
floating-point floats and a thousand other things, then NaNs stand out as the 
values that have special algorithm-breaking magic.


I gave an example of such an algorithm in an earlier reply to Chris.

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Chris Angelico
On Thu, Jul 10, 2014 at 1:08 AM, Anders J. Munch 2...@jmunch.dk wrote:
 Steven D'Aprano wrote:

 It seems to me that the trivial work-around is:

 * gather packed floats from some device, as ints
 * process them *as ints* in some way which requires reflexivity
 * unpack back into floats
 * (maybe) much later perform numeric calculations on them


 Although perhaps I don't understand your use-case.


 Clearly you do not. floats are not ints. I have no idea how you imagine
 processing IEEE-754 floating-point values in int form.

 My use case is: Working with IEEE-754 floating-point values. That means
 storing and retrieving them, serialising and transferring them, accepting
 them as user input, printing them, all the usual things you do with values.

 And doing so in a way that does not require special handling in algorithms
 that are otherwise generic.
 When the same algorithm is capable of dealing with ints, bytestrings, text
 string, tuples, list, dictionaries, time stamps, NoneType's, bools,
 floating-point floats and a thousand other things, then NaNs stand out as
 the values that have special algorithm-breaking magic.

 I gave an example of such an algorithm in an earlier reply to Chris.

If you need to do bitwise comparisons, then the easiest way is to use
the bitpattern, converted to an integer. A 64-bit float becomes a
64-bit integer. It's then very simple to compare them, and reflexivity
is maintained. At what point do you actually need them to be floats?
What are you really doing with them?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

Chris Angelico:

If you need to do bitwise comparisons, then the easiest way is to use
the bitpattern, converted to an integer. A 64-bit float becomes a
64-bit integer. It's then very simple to compare them, and reflexivity
is maintained. At what point do you actually need them to be floats?
What are you really doing with them?


What does one do with floats? Add, subtract, multipy, divide, display, input, 
store and retrieve to and from various formats.

All the usual stuff. Why would my use be different from anyone elses?

What you and Steven seem to be saying is that I should employ strategies to 
avoid NaNs ever being compared. I'll take that one step further and say that as 
long as NaN!=NaN, everyone should seek to avoid NaNs ever being compared.


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ethan Furman

On 07/08/2014 07:53 AM, Anders J. Munch wrote:


So I make this claim: float.__eq__ implementing IEEE-754 NaN
comparison rules creates real problems for developers. And it has
never, ever, helped anyone do anything.

Never is a strong claim, and easily disproven if false: Simply
provide a counterexample.  So that is my challenge: If you have a
program (a pre-existing and useful one, not something artificial
created for this challenge) that benefits from NaN!=NaN and that would
fail if x==x for all float objects x, then please come forward and
show it, and I'll buy you a beer the next time I'm at PyCon.


I would suggest you ask for this on the numerical mailing lists instead of here -- and you may not want to offer a beer 
to everyone that has an anecdote for NaN behavior being useful.


--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Steven D'Aprano
On Wed, 09 Jul 2014 17:08:15 +0200, Anders J. Munch wrote:

 Steven D'Aprano wrote:
 It seems to me that the trivial work-around is:

 * gather packed floats from some device, as ints * process them *as
 ints* in some way which requires reflexivity * unpack back into floats
 * (maybe) much later perform numeric calculations on them


 Although perhaps I don't understand your use-case.
 
 Clearly you do not. floats are not ints. 

Of course not. But there is a one-to-one correspondence between a 64-bit 
float and a 64-bit int, and the conversion is lossless in both directions.

When you talked about:

So when my software reads these values in binary, unpack them using the
struct module, and goes to work.

I assumed that you realised that the 64-bit(?) values you were receiving 
in binary could be interpreted as ints. After all, you have to unpack 
them from some bytes.

Since that's not what you're doing, I have no idea what it is.


 I have no idea how you imagine
 processing IEEE-754 floating-point values in int form.

Cast your 64-bit float into a 64-bit int. Or, if it's a C single rather 
than a double, cast the 32-bit float into a 32-bit int. Now you can 
compare them for equality without carrying about NANs, and without losing 
data. Later, when you're ready to start doing some numeric work on them, 
you cast back to floats. That's the idea I had in mind. Perhaps it 
doesn't match your use-case.


 My use case is: Working with IEEE-754 floating-point values. That means
 storing and retrieving them, serialising and transferring them,
 accepting them as user input, printing them, all the usual things you do
 with values.

But apparently not arithmetic?


 And doing so in a way that does not require special handling in
 algorithms that are otherwise generic.

Ah, well there's your problem. NANs are special, as a signed zeroes and 
INFs. Does it distress you that x + x = x when x is an INF?


 When the same algorithm is capable of dealing with ints, bytestrings,
 text string, tuples, list, dictionaries, time stamps, NoneType's, bools,
 floating-point floats and a thousand other things, 
  ^

Obviously not, or you wouldn't be complaining about the inability to 
handle floats.

The hardware devices generating your float data... do they also generate 
ints, bytestrings, text strings, tuples, lists, dicts, time stamps, None, 
bools, and a thousand other things? If not, I wonder why you are 
insisting that you have to handle a *specialised* data type using a 
*generic* algorithm.


 then NaNs stand out
 as the values that have special algorithm-breaking magic.

Well yes. Floats have all sorts of problems. They're horrible really, the 
worst possible way to model real numbers, except for all the other ways.

I'm not unsympathetic to your problem, which is why I proposed two new 
operators, === and !==, and a change to == and !=, in another thread. 
Would == always doing an identity test before calling __eq__ solve your 
problem? If not, what would it take to solve your problem?


-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ian Kelly
On Wed, Jul 9, 2014 at 10:53 AM, Steven D'Aprano
 Cast your 64-bit float into a 64-bit int. Or, if it's a C single rather
 than a double, cast the 32-bit float into a 32-bit int. Now you can
 compare them for equality without carrying about NANs, and without losing
 data. Later, when you're ready to start doing some numeric work on them,
 you cast back to floats. That's the idea I had in mind. Perhaps it
 doesn't match your use-case.

Unfortunately, it's not that simple:

 import math, struct
 def float_to_int(x):
...   return struct.unpack('L', struct.pack('d', x))[0]
...
 0.0 == -0.0
True
 float_to_int(0.0) == float_to_int(-0.0)
False
 nan1 = struct.unpack('d', b'\x00'*6+b'\xf1\x7f')[0]
 math.isnan(nan1)
True
 nan2 = struct.unpack('d', b'\x00'*6+b'\xf2\x7f')[0]
 math.isnan(nan2)
True
 float_to_int(nan1) == float_to_int(nan1)
True
 float_to_int(nan2) == float_to_int(nan2)
True
 float_to_int(nan1) == float_to_int(nan2)
False
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

Steven D'Aprano wrote:

I assumed that you realised that the 64-bit(?) values you were receiving
in binary could be interpreted as ints. After all, you have to unpack
them from some bytes.



Since that's not what you're doing, I have no idea what it is.


Stop obsessing over how NaN's came to exist in my software. That's just context.
The argument is over how those NaNs should behave. Their provenance is not 
relevant.


I have no idea how you imagine
processing IEEE-754 floating-point values in int form.

Cast your 64-bit float into a 64-bit int.


I can construct a bijective mapping between any data structure and a subset of 
the natural numbers, but that has nothing to do with practical programming.

A cast value would be impossible to work with.




My use case is: Working with IEEE-754 floating-point values. That means
storing and retrieving them, serialising and transferring them,
accepting them as user input, printing them, all the usual things you do
with values.

But apparently not arithmetic?
Of course also arithmetic. I left it out of the list because then you would say 
hah! if you're doing arithmetic then it's not a generic algorithm. Apparently 
I can't win, you are going to nitpick anything I write.


Ah, well there's your problem. NANs are special, as a signed zeroes and INFs. 
Does it distress you that x + x = x when x is an INF?

No.


When the same algorithm is capable of dealing with ints, bytestrings,
text string, tuples, list, dictionaries, time stamps, NoneType's, bools,
floating-point floats and a thousand other things,

   ^

Obviously not, or you wouldn't be complaining about the inability to
handle floats.


NaNs are not floating-point values. A floating-point value has a sign, an 
exponent and a mantissa.  They are IEEE 754 floating point values, though.



The hardware devices generating your float data... do they also generate
ints, bytestrings, text strings, tuples, lists, dicts, time stamps, None,
bools, and a thousand other things? If not, I wonder why you are
insisting that you have to handle a *specialised* data type using a
*generic* algorithm.
All the other types are also specialised, for their separate purpose. That 
doesn't make them non-reflexive.




I'm not unsympathetic to your problem, which is why I proposed two new
operators, === and !==, and a change to == and !=, in another thread.
Would == always doing an identity test before calling __eq__ solve your
problem? If not, what would it take to solve your problem?

It would not solve it. Two bitwise identical NaNs would still compare different.
What would solve the problem is making identical NaNs compare equal.

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

Ethan Furman:
I would suggest you ask for this on the numerical mailing lists instead of 
here -- and you may not want to offer a beer to everyone that has an anecdote 
for NaN behavior being useful.
I don't have time to start this discussion over again on another mailing list. 
Don't anyone on those lists read python-list also?


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Joel Goldstick
On Wed, Jul 9, 2014 at 5:09 PM, Anders J. Munch 2...@jmunch.dk wrote:

 Ethan Furman:

  I would suggest you ask for this on the numerical mailing lists instead
 of here -- and you may not want to offer a beer to everyone that has an
 anecdote for NaN behavior being useful.

 I don't have time to start this discussion over again on another mailing
 list. Don't anyone on those lists read python-list also?


I've been following along here, and it seems you haven't received the
answer you want or need.  Since you are the one in search of a solution it
seems that you might take more kindly to a pointer in a direction that
might serve you better.  Best of luck



 regards, Anders

 --
 https://mail.python.org/mailman/listinfo/python-list




-- 
Joel Goldstick
http://joelgoldstick.com
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ethan Furman

On 07/09/2014 02:09 PM, Anders J. Munch wrote:

Ethan Furman:


I would suggest you ask for this on the numerical mailing lists instead of here 
-- and you may not want to offer a
beer to everyone that has an anecdote for NaN behavior being useful.


I don't have time to start this discussion over again on another mailing list. 
Don't anyone on those lists read
python-list also?


I believe there are a handful, but I don't know how active they are here.  For a straight-up numbers type question, 
especially about NaN and who's using it to what effect, a numbers or scientific mailing list is really the way to go.


--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Anders J. Munch

Joel Goldstick wrote:
I've been following along here, and it seems you haven't received the answer 
you want or need.


So far I received exactly the answer I was expecting.  0 examples of NaN!=NaN 
being beneficial.
I wasn't asking for help, I was making a point.  Whether that will lead to 
improvement of Python, well, I'm not too optimistic, but I feel the point was 
worth making regardless.


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ian Kelly
On Wed, Jul 9, 2014 at 5:03 PM, Anders J. Munch 2...@jmunch.dk wrote:
 Joel Goldstick wrote:

 I've been following along here, and it seems you haven't received the
 answer you want or need.


 So far I received exactly the answer I was expecting.  0 examples of
 NaN!=NaN being beneficial.
 I wasn't asking for help, I was making a point.  Whether that will lead to
 improvement of Python, well, I'm not too optimistic, but I feel the point
 was worth making regardless.

If the reason there were 0 examples is because the group that you
posed the question to is lacking the kind of experience needed to be
able to provide them (speaking for myself, I wouldn't know because I
don't ever do anything with NaN beyond checking for it as an error
condition), then the point hasn't really been made, has it?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ethan Furman

On 07/09/2014 04:03 PM, Anders J. Munch wrote:

Joel Goldstick wrote:


I've been following along here, and it seems you haven't received the answer 
you want or need.


So far I received exactly the answer I was expecting.  0 examples of NaN!=NaN 
being beneficial.


python-list (in whichever from you interact with it) is in no way specialized, yet you are asking for a highly 
specialized bit of information.



I wasn't asking for help, I was making a point.  Whether that will lead to 
improvement of Python, well, I'm not too
optimistic, but I feel the point was worth making regardless.


The only point you have made is that no-one here uses them much.  You could just as easily ask how many of us use 
lead-alloy to shield our in-home nuclear reactors to get the same answer.


On the other hand, if you go and ask on the numpy and simpy and whatever-math-or-science-py lists there are, and get 
affirmative answers from them that yeah, NaN != NaN is just a huge pain and everyone is working around it, then brought 
that information back here -- well, then you will have made the point that you want to make.


--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Ben Finney
Anders J. Munch 2...@jmunch.dk writes:

 Joel Goldstick wrote:
  I've been following along here, and it seems you haven't received
  the answer you want or need.

 So far I received exactly the answer I was expecting. 0 examples of
 NaN!=NaN being beneficial.

Predictability and ease of diagnosis are the principles at work
URL:http://stackoverflow.com/a/1573715/70157. You have already
received examples of those.

If those don't convince you of its usefulness, that's unfortunate, but
at this point you are demonstrating a standard which is both
unreasonably high (even the rationale of the committee doesn't convince
you) and unreasonably low (you ask not for explanations but personal
anecdotes).

Good luck to you in your quest.

-- 
 \  “Every man would like to be God, if it were possible; some few |
  `\  find it difficult to admit the impossibility.” —Bertrand |
_o__)Russell, _Power: A New Social Analysis_, 1938 |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-09 Thread Rustom Mody
On Tuesday, July 8, 2014 8:23:47 PM UTC+5:30, Anders J. Munch wrote:
 Most people don't need to deal with NaN's in Python at all,
 fortunately. They just don't appear in normal computation, because the
 interpreter raises an exception instead.

 So I make this claim: float.__eq__ implementing IEEE-754 NaN
 comparison rules creates real problems for developers. And it has
 never, ever, helped anyone do anything.

 Never is a strong claim, and easily disproven if false: Simply
 provide a counterexample.  So that is my challenge: If you have a

No I dont have a direct answer for your challenge but I have two close 
analogies.

Nan in floats is analogous (almost isomorphic) to two other areas
- null in RDBMS
- bottom – ⊥ – in denotational semantics 

The denotational semantics example would really clarify the issue.
I have discussed it here in the haskell context:
http://blog.languager.org/2012/08/functional-programming-philosophical.html

http://en.wikibooks.org/wiki/Haskell/Denotational_semantics#.E2.8A.A5_Bottom
is a more general survey

RDBMS nulls is probably a more familiar example.

Lets say you have a dbms of people and one nullable field is 'telephone'.

Now some people have no phones and the original intent of the nullable 
field was to take care of that.

But then in data entry some people who had too many phones and could not
decide which to fill kept the field null!!

Are these two cases equivalent?  Your request amounts to making them so.

Now read your own case:

 It happens in my work I come across them quite a lot. I'm writing
 software that talks to embedded applications that can contain NaN
 values for a variety of reasons - never-initialised storage,
 initialise-to-NaN, hardware failures etc.

How do you decide that all these are equivalent/ 'equal'?

Someone or other somewhere or other will be unhappy!!

My analysis of the problem:

The *letter* of the IEEE standard describes nans (and other exotic beasties)
The *spirit* describes exceptional conditions that arise in floating 
computations
[I have not read the standard -- just guessing]

The standard was made when programming languages did not have well tried and
tested exception mechanisms.

So with python supporting nans we have two competing exception mechanisms:
- the IEEE one -- nans
- the native python one -- exceptions

Once this is clear it should be clear what the solution should be:
DRY, no redundancy etc.

Since exceptions are pythonic, nans should not be supported.

If we were starting from scratch this would be the way to go.
However given the currently extant support, this would be a downgrade for
people like you -- who would be unhappy!

So intermediate more kludgy solution:

The problem is not with

 nan==nan
False

But with

 type(nan)
class 'float'

So nan is a float but by definition is not a number!!

So float a superset of all numbers??!!

If instead like:
 type(None)
class 'NoneType'

we had
 type(None)
class 'NanType'

then normal users would never see it
and people like you could deal with it outside the float-umbrella.
-- 
https://mail.python.org/mailman/listinfo/python-list


NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch

Most people don't need to deal with NaN's in Python at all,
fortunately. They just don't appear in normal computation, because the
interpreter raises an exception instead.

It happens in my work I come across them quite a lot. I'm writing
software that talks to embedded applications that can contain NaN
values for a variety of reasons - never-initialised storage,
initialise-to-NaN, hardware failures etc.

So when my software reads these values in binary, unpack them using
the struct module, and goes to work. And NaN's are no different from
any other value, it's something to store, compare, display etc.

And that worked fine in my Python 2.4 apps.  Then I upgraded to 2.7
and it broke.  Because 2.7 goes out of it's way to ensure that NaN's
don't compare equal to themselves.

I discovered it when a sanity check told me that two functions,
to_binary and from_binary, weren't each other's inverse, as they were
intended to be.  Apparently,
bitPattern==to_binary(from_binary(bitPattern)) wasn't true for this
particular value of bitPattern.  Of course, the bit pattern in
question was the binary representation for a floating-point NaN.

Panic time! If I can't trust == to return True for (mathematically)
equal objects, that means that every single algorithm I had ever written
that explicitly or implicitly does .__eq__ or .__ne__ comparison was
suspect!

That meant I had 3 lines of code to review.  Every time there's a
comparison, if there was any chance that either value could be a
float NaN, I would have to change e.g.
   if x==y:
to
   if x==y or (isinstance(x, float) and isinstance(y, float) and
 math.isnan(x) and math.isnan(y)):
To make it bearable, I could wrap the pattern up in a function and
write
   if my_equal(x,y):
but I would still lose, because the standard library does == and !=
all over the place without calling my_equal.

In the end I came up with this hack: Every time I struct.unpack'd a
float, I check if it's a NaN, and if it is, then I replace it with a
reference to a single, shared, canonical NaN. That means that
container objects that skip __equal__ when comparing an object to
itself will work -- e.g. hash keys.

It's half a solution, of course: Any further computation with a NaN
value will change it to a different NaN object, so I still needed to
do explicit NaN-checks in various places.  I'm sure there are still
NaN-related bugs in my code, but right now it's good enough - I
haven't seen NaN-related bugs in a good while.

Now, all this bothers me.  Not that I had to do some work to get stuff
to work in an imperfect world.  No, what bothers me is that this
behaviour was explicitly and deliberately put in for no good reason.
The only reason is standard says so. Not that there's any legal
requirement for Python to follow the IEEE-754 standard. Or for that
matter, for Python's spelling of IEEE-754 comparisons to be ==.

So I make this claim: float.__eq__ implementing IEEE-754 NaN
comparison rules creates real problems for developers. And it has
never, ever, helped anyone do anything.

Never is a strong claim, and easily disproven if false: Simply
provide a counterexample.  So that is my challenge: If you have a
program (a pre-existing and useful one, not something artificial
created for this challenge) that benefits from NaN!=NaN and that would
fail if x==x for all float objects x, then please come forward and
show it, and I'll buy you a beer the next time I'm at PyCon.

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 12:53 AM, Anders J. Munch 2...@jmunch.dk wrote:
 In the end I came up with this hack: Every time I struct.unpack'd a
 float, I check if it's a NaN, and if it is, then I replace it with a
 reference to a single, shared, canonical NaN. That means that
 container objects that skip __equal__ when comparing an object to
 itself will work -- e.g. hash keys.

Let's take a step back.

No, let's take a step forward.

And let's take a step back again.

(And we're building a military-grade laser!)

Why *should* all NaNs be equal to each other? You said on the other
list that NaN==NaN was equivalent to (2+2)==(1+3), but that assumes
that NaN is a single thing. It's really describing the whole huge
area of stuff that just ain't numbers. Imagine if (x + y) wasn't 4,
but was table. And (a + b) turned out to be cyan. Does table equal
cyan, just because neither of them is a number? Certainly not. Neither
should (inf - inf) be equal to (inf / inf). Both of those expressions
evaluate to something that can't possibly be a number - it can't be
anywhere on the number line, it can't be anywhere on the complex
plane, it simply isn't a number. And they're not the same non-numeric
thing.

For hash keys, float object identity will successfully look them up:
 d={}
 d[float(nan)]=1
 d[float(nan)]=2
 x=float(nan)
 d[x]=3
 d[x]
3
 d
{nan: 1, nan: 2, nan: 3}

So I'm not sure where the problems come from. You can iterate over a
dict's keys and look things up with them:

 for k,v in d.items():
print(k,v,d[k])
nan 1 1
nan 2 2
nan 3 3

You can do a simple 'is' check as well as your equality check:

if x is y or x == y:
print(They're the same)

But any time you compare floats for equality, you *already* have to
understand what you're doing (because of rounding and such), so I
don't see why the special case on NaN is significant, unless as
mentioned above, you want all NaNs to be equal, which doesn't make
sense.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ian Kelly
On Tue, Jul 8, 2014 at 8:53 AM, Anders J. Munch 2...@jmunch.dk wrote:
 And that worked fine in my Python 2.4 apps.  Then I upgraded to 2.7
 and it broke.  Because 2.7 goes out of it's way to ensure that NaN's
 don't compare equal to themselves.

As far as I know nothing changed between 2.4 and 2.7 in this regard.
Python has always had NaN compare unequal to everything, per the
standard.

 I discovered it when a sanity check told me that two functions,
 to_binary and from_binary, weren't each other's inverse, as they were
 intended to be.  Apparently,
 bitPattern==to_binary(from_binary(bitPattern)) wasn't true for this
 particular value of bitPattern.  Of course, the bit pattern in
 question was the binary representation for a floating-point NaN.

Okay, here's your problem: there isn't just one binary representation
for NaN.  The standard defines any value with all 1's in the exponent
and a non-zero significand as NaN (a zero significand would instead be
an infinity).  Your bit comparison is going to have to be prepared to
compare NaNs that don't have the same binary representation.

By the way, there are also multiple binary representations for 0.  If
you compare them as floats, then they'll compare equal to one another,
but if you're just comparing binary representations then you'll have
issues there as well.

 Now, all this bothers me.  Not that I had to do some work to get stuff
 to work in an imperfect world.  No, what bothers me is that this
 behaviour was explicitly and deliberately put in for no good reason.
 The only reason is standard says so. Not that there's any legal
 requirement for Python to follow the IEEE-754 standard. Or for that
 matter, for Python's spelling of IEEE-754 comparisons to be ==.

Following the standard isn't a good reason itself?  It seems to me
that one should be expected to provide a strong justification for
*deviating* from the standard, not for following it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Skip Montanaro
On Tue, Jul 8, 2014 at 10:19 AM, Chris Angelico ros...@gmail.com wrote:
 For hash keys, float object identity will successfully look them up:
 d={}
 d[float(nan)]=1
 d[float(nan)]=2
 x=float(nan)
 d[x]=3
 d[x]
 3
 d
 {nan: 1, nan: 2, nan: 3}

Neat!

S
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 1:24 AM, Skip Montanaro s...@pobox.com wrote:
 On Tue, Jul 8, 2014 at 10:19 AM, Chris Angelico ros...@gmail.com wrote:
 For hash keys, float object identity will successfully look them up:
 d={}
 d[float(nan)]=1
 d[float(nan)]=2
 x=float(nan)
 d[x]=3
 d[x]
 3
 d
 {nan: 1, nan: 2, nan: 3}

 Neat!

Yeah. It's one of those arguable points; is it a mere optimization
that dict lookup does an identity check before an equality check, or
is it crucial to other invariants (like the iteration one - if you
iterate over items(), it should give exactly the same results as
iterating over keys() and then looking things up)? Obviously it's
better for the dict to use equality checks rather than identity checks
(otherwise, at the very least, you'd have to explicitly intern all
strings used as dict keys - that'd just be ridiculous), but with
objects that don't compare equal to themselves, what should be done?

I think Python's picked a quite reasonable approach.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Marko Rauhamaa
Chris Angelico ros...@gmail.com:

 Why *should* all NaNs be equal to each other?

I appreciate why you can't say NaN is equal to NaN. However, shouldn't
the very comparison attempt trigger an arithmetic exception? After all,
so does a division by zero.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 2:16 AM, Marko Rauhamaa ma...@pacujo.net wrote:
 Chris Angelico ros...@gmail.com:

 Why *should* all NaNs be equal to each other?

 I appreciate why you can't say NaN is equal to NaN. However, shouldn't
 the very comparison attempt trigger an arithmetic exception? After all,
 so does a division by zero.

I'd say it would surprise people rather a lot if operations like dict
insertion/lookup could trigger arithmetic exceptions. :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 16:53:47 +0200, Anders J. Munch wrote:

 Most people don't need to deal with NaN's in Python at all, fortunately.
 They just don't appear in normal computation, because the interpreter
 raises an exception instead.
 
 It happens in my work I come across them quite a lot. I'm writing
 software that talks to embedded applications that can contain NaN values
 for a variety of reasons - never-initialised storage, initialise-to-NaN,
 hardware failures etc.
 
 So when my software reads these values in binary, unpack them using the
 struct module, and goes to work. And NaN's are no different from any
 other value, it's something to store, compare, display etc.
 
 And that worked fine in my Python 2.4 apps.

I think you're smoking something funny :-)


[steve@ando ~]$ python2.4
Python 2.4.3 (#1, Jan  9 2013, 06:49:54)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)] on linux2
Type help, copyright, credits or license for more information.
py NAN = float('NAN')
py NAN == NAN
False


NANs compared unequal in Python 2.4.



[...]
 Now, all this bothers me.  Not that I had to do some work to get stuff
 to work in an imperfect world.  No, what bothers me is that this
 behaviour was explicitly and deliberately put in for no good reason.

Oh, you've read the IEEE-754 standard, and that's what it says? We're 
going to specify this behaviour for NANs just to annoy people perhaps?



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 3:13 AM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 Now, all this bothers me.  Not that I had to do some work to get stuff
 to work in an imperfect world.  No, what bothers me is that this
 behaviour was explicitly and deliberately put in for no good reason.

 Oh, you've read the IEEE-754 standard, and that's what it says? We're
 going to specify this behaviour for NANs just to annoy people perhaps?

You're confusing IEEE with Adobe. IEEE is pronounced
Ai!, but it's Adobe that makes people scream
that.

http://www.theregister.co.uk/2009/04/30/xee_photoshop_psd_code_rant/

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Skip Montanaro
On Tue, Jul 8, 2014 at 9:53 AM, Anders J. Munch 2...@jmunch.dk wrote:
 Most people don't need to deal with NaN's in Python at all,
 fortunately. They just don't appear in normal computation, because the
 interpreter raises an exception instead.

In addition to what others have written, I will add one thing. There
are certainly situations where raising an exception is bad. Consider
all the people in the scientific computing community doing fancy
linear algebra sorts of things, often with missing data. They
generally want NaN propagated and not have some long running
calculation crash in the middle.

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Marko Rauhamaa
Chris Angelico ros...@gmail.com:

 I'd say it would surprise people rather a lot if operations like dict
 insertion/lookup could trigger arithmetic exceptions. :)

That wouldn't trigger exceptions.

Dict operations do an is test before an == test. In fact, you
couldn't even use NaN as a dict key otherwise. Thus, dict operations
never test NaN == NaN.


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Marko Rauhamaa
Skip Montanaro s...@pobox.com:

 In addition to what others have written, I will add one thing. There
 are certainly situations where raising an exception is bad. Consider
 all the people in the scientific computing community doing fancy
 linear algebra sorts of things, often with missing data. They
 generally want NaN propagated and not have some long running
 calculation crash in the middle.

Do the scientific computers mind:

 1 / 0
Traceback (most recent call last):
  File stdin, line 1, in module
ZeroDivisionError: division by zero

or would they prefer their fancy linear-algebraic computation to just
forge on?


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Skip Montanaro
 import numpy
 a1 = numpy.ones(5)
 a1
array([ 1.,  1.,  1.,  1.,  1.])
 a0 = numpy.zeros(5)
 a0
array([ 0.,  0.,  0.,  0.,  0.])
 a1 / a0
__main__:1: RuntimeWarning: divide by zero encountered in true_divide
array([ inf,  inf,  inf,  inf,  inf])
 nans = numpy.array([float(nan)] * 5)
 nans
array([ nan,  nan,  nan,  nan,  nan])
 a1 / nans
array([ nan,  nan,  nan,  nan,  nan])
 a1 / a0 * nans
array([ nan,  nan,  nan,  nan,  nan])

You get a runtime warning (this is in Python 2.7), but the division
returns the appropriate value, in this case, infinity. So, yes, they
forge on, and NaN taints things just about the way you'd expect.

Skip

On Tue, Jul 8, 2014 at 12:36 PM, Marko Rauhamaa ma...@pacujo.net wrote:
 Skip Montanaro s...@pobox.com:

 In addition to what others have written, I will add one thing. There
 are certainly situations where raising an exception is bad. Consider
 all the people in the scientific computing community doing fancy
 linear algebra sorts of things, often with missing data. They
 generally want NaN propagated and not have some long running
 calculation crash in the middle.

 Do the scientific computers mind:

  1 / 0
 Traceback (most recent call last):
   File stdin, line 1, in module
 ZeroDivisionError: division by zero

 or would they prefer their fancy linear-algebraic computation to just
 forge on?


 Marko
 --
 https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 3:31 AM, Marko Rauhamaa ma...@pacujo.net wrote:
 Chris Angelico ros...@gmail.com:

 I'd say it would surprise people rather a lot if operations like dict
 insertion/lookup could trigger arithmetic exceptions. :)

 That wouldn't trigger exceptions.

 Dict operations do an is test before an == test. In fact, you
 couldn't even use NaN as a dict key otherwise. Thus, dict operations
 never test NaN == NaN.

Check out the example I posted early in this thread of a dict with
three keys, all of them NaN. And note that hash(float(nan))==0. Now
try looking up d[0]. Before it raises KeyError, it has to compare that
0 for equality with each of the nans, because it can't shortcut it
based on the hash. In fact, I can prove it thus:

 class X:
def __eq__(self, other):
if self is other:
print(Comparing against self - I am me!)
return True
print(Comparing against,other,-,id(other))
return False
def __hash__(self):
return 0

 d[X()]
Comparing against nan - 18777952
Comparing against nan - 19624864
Comparing against nan - 18776272
Traceback (most recent call last):
  File pyshell#20, line 1, in module
d[X()]
KeyError: __main__.X object at 0x016B40D0

Any lookup of anything with a hash of 0 will do this. 0 itself (as any
type of number), another NaN, or anything at all. For the dict to work
sanely, these comparisons have to work and be False.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 3:54 AM, Chris Angelico ros...@gmail.com wrote:
 class X:
 def __eq__(self, other):
 if self is other:
 print(Comparing against self - I am me!)
 return True
 print(Comparing against,other,-,id(other))
 return False
 def __hash__(self):
 return 0

 d[X()]
 Comparing against nan - 18777952
 Comparing against nan - 19624864
 Comparing against nan - 18776272
 Traceback (most recent call last):
   File pyshell#20, line 1, in module
 d[X()]
 KeyError: __main__.X object at 0x016B40D0

Better example: Subclass float, then it can actually *be* a nan.

 class NoisyFloat(float):
def __eq__(self, other):
print(Comparing,id(self),against,id(other))
return super().__eq__(other)
def __hash__(self):
return super().__hash__()

 d[NoisyFloat(nan)]
Comparing 23777152 against 18777952
Comparing 23777152 against 19624864
Comparing 23777152 against 18776272
Traceback (most recent call last):
  File pyshell#35, line 1, in module
d[NoisyFloat(nan)]
KeyError: nan

That's comparing nan==nan three types with four different nans.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ethan Furman

On 07/08/2014 07:53 AM, Anders J. Munch wrote:


Most people don't need to deal with NaN's in Python at all,
fortunately. They just don't appear in normal computation, because the
interpreter raises an exception instead.


What exception?  Apparently your claims about NaN in Python are all 
wrong -- have you been using a custom interpreter?


Python 2.7.4 (default, Sep 26 2013, 03:20:26)
[GCC 4.7.3] on linux2
Type help, copyright, credits or license for more information.
 float('inf') - float('inf')
nan

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 20:31:25 +0300, Marko Rauhamaa wrote:

 Thus, dict operations never test NaN == NaN

You're assuming that there is only one NAN instance. That is not correct:

py a = float('nan')
py b = float('nan')
py a is b
False
py a in {b: None}
False



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 19:16:53 +0300, Marko Rauhamaa wrote:

 Chris Angelico ros...@gmail.com:
 
 Why *should* all NaNs be equal to each other?
 
 I appreciate why you can't say NaN is equal to NaN. However, shouldn't
 the very comparison attempt trigger an arithmetic exception? 

No. Why should it? It's not an error to check whether two things are 
equal.


 After all, so does a division by zero.

Um, yes, and multiplying by zero isn't an error. In what way is x == y 
related to x/0 ?


But having said that, sometimes it is useful to stop processing as soon 
as you reach a NAN. For that, IEEE-754 defines two kinds of NANs, Quiet 
NANs and Signalling NANs. Quiet NANs don't trigger a signal when you 
perform operations on them. (By default -- I believe you can enable 
signals if you wish.) Signalling NANs always trigger a signal, including 
when you check them for equality:


py from decimal import Decimal as D
py a = D('nan')
py b = D('snan')
py 1 == a
False
py 1 == b
Traceback (most recent call last):
  File stdin, line 1, in module
decimal.InvalidOperation: [class 'decimal.InvalidOperation']


But by default, NANs are quiet. The C99 standard doesn't support 
signalling NANs, and Java actually prohibits them.

Aside: The influence of C and Java has crippled IEEE-754 support across 
almost all languages and hardware. It's a crying shame the pernicious 
influence those two languages have had.

http://grouper.ieee.org/groups/1788/email/pdfmPSi1DgZZf.pdf

Floating point is *hard*, and people who don't understand it insist on 
telling those who do that you don't need that feature :-(



-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch

Chris Angelico wrote:


Why *should* all NaNs be equal to each other? You said on the other
list that NaN==NaN was equivalent to (2+2)==(1+3), but that assumes
that NaN is a single thing.


I don't actually care if all NaN bitpatterns are in the same equivalence group 
or if each bitpattern is its own equivalence group. I just want the == 
equivalence relation to be sound.



For hash keys, float object identity will successfully look them up:


Except you can't expect to rely on object identity in most interesting cases.

 x = float('nan')
 import struct
 y = struct.unpack('f', struct.pack('f', x))[0]
 d[x] = found
 d[y]
Traceback (most recent call last):
File stdin, line 1, in module
KeyError: nan

and also:

 def f(): return float('inf')/float('inf')
 f() == f()
False
 f() is f()
False


But any time you compare floats for equality, you *already* have to
understand what you're doing (because of rounding and such), so I
don't see why the special case on NaN is significant, unless as
mentioned above, you want all NaNs to be equal, which doesn't make
sense.

Let me conjure up a simple example:

| class Monitor(Thread):
| def run(self):
| old = self.get_current_value()
| while not self.Terminated:
| new = self.get_current_value()
| if new != old:
| print(time.asctime(), changed to, new)
| old = new
| time.sleep(1)

This is a completely generic change detection algorithm, and not a 
floating-point algorithm in any way: It will work on strings, lists, sets, 
anything that get_current_value returns, including non-NaN floats. You don't 
need to know anything about floating-point representation to write or use such 
an algorithm, why should you? It works on tuples, sets, lists, serial port 
handles, module objects, pretty much anything you can imagine -- except NaN floats.


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Chris Angelico
On Wed, Jul 9, 2014 at 4:29 AM, Anders J. Munch 2...@jmunch.dk wrote:
 Chris Angelico wrote:
 For hash keys, float object identity will successfully look them up:


 Except you can't expect to rely on object identity in most interesting
 cases.

 x = float('nan')
 import struct
 y = struct.unpack('f', struct.pack('f', x))[0]
 d[x] = found
 d[y]

 Traceback (most recent call last):
 File stdin, line 1, in module
 KeyError: nan

 and also:

 def f(): return float('inf')/float('inf')
 f() == f()
 False
 f() is f()
 False

Neither of those examples is anything to do with object identity. In
the first case, you pack the value and recreate an equivalent of the
same type with the same value. In the second, you independently
construct two floats with the same value. Both times, you have
equivalence (both are NaN), but not identical objects.

 Let me conjure up a simple example:

 | class Monitor(Thread):
 | def run(self):
 | old = self.get_current_value()
 | while not self.Terminated:
 | new = self.get_current_value()
 | if new != old:
 | print(time.asctime(), changed to, new)
 | old = new
 | time.sleep(1)

 This is a completely generic change detection algorithm, and not a
 floating-point algorithm in any way: It will work on strings, lists, sets,
 anything that get_current_value returns, including non-NaN floats. You don't
 need to know anything about floating-point representation to write or use
 such an algorithm, why should you? It works on tuples, sets, lists, serial
 port handles, module objects, pretty much anything you can imagine -- except
 NaN floats.

You also have to cope with objects that define __eq__ or __ne__. If
you know that you have a monitor like that, then you make sure that
the value is something comparable; there are plenty of reasons to have
to be careful there. (Consider, for instance, what happens if
get_current_value() returns a list. Mutating that list can change
whether or not it's equal to something else.)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch


Ian Kelly wrote:

As far as I know nothing changed between 2.4 and 2.7 in this regard.
Python has always had NaN compare unequal to everything, per the
standard.

It might have been platform-specific in 2.4.


Okay, here's your problem: there isn't just one binary representation
for NaN.
I'm fully aware of that. Whether NaN's are one equivalence class or several is 
not the issue. What matters is the integrity of the equivalence relation.


Following the standard isn't a good reason itself? 


If a standard tells you to jump of a cliff...

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch

Steven D'Aprano wrote:
Oh, you've read the IEEE-754 standard, and that's what it says? We're going 
to specify this behaviour for NANs just to annoy people perhaps? 
I was referring to the deliberate choice to enforce IEEE-754 rules in Python. 
There is no force of law that requires Python to do so.


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch

Ethan Furman skrev:
What exception? Apparently your claims about NaN in Python are all wrong -- 
have you been using a custom interpreter?

 float('inf') - float('inf')
nan

If you deliberately try to manufacture NaN's, you can. I never said otherwise.

regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch


Den 14-07-08 19:23, Skip Montanaro skrev:


In addition to what others have written, I will add one thing. There
are certainly situations where raising an exception is bad. Consider
all the people in the scientific computing community doing fancy
linear algebra sorts of things, often with missing data. They
generally want NaN propagated and not have some long running
calculation crash in the middle.


NaN!=NaN doesn't cause NaN's to propagate any more or any less. It simply causes 
a different branch of code to run, quite often the wrong one.


regards, Anders

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Anders J. Munch

I wrote:

Steven D'Aprano wrote:
Oh, you've read the IEEE-754 standard, and that's what it says? We're going 
to specify this behaviour for NANs just to annoy people perhaps? 
I was referring to the deliberate choice to enforce IEEE-754 rules in Python. 
There is no force of law that requires Python to do so.




And just to be clear, I didn't mean python-dev did this to annoy people either. 
I just meant that the choice made is not supported by any use case, so there's 
no upside to outweigh the problems it creates.


At least I've yet to hear any use case. So far I'm 0 beers in debt.

regards, Anders
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ethan Furman

On 07/08/2014 12:04 PM, Anders J. Munch wrote:

Ethan Furman skrev:


What exception? Apparently your claims about NaN in Python are all wrong -- 
have you been using a custom interpreter?
 float('inf') - float('inf')
nan


If you deliberately try to manufacture NaN's, you can. I never said otherwise.


What you said is: They just don't appear in normal computation, because the
interpreter raises an exception instead.

I just ran a calculation that created a NaN, the same as 4 - 3 creates a 1, and 
no exception was raised.

Do you have an example where one is?

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ian Kelly
On Tue, Jul 8, 2014 at 1:16 PM, Ethan Furman et...@stoneleaf.us wrote:
 What you said is: They just don't appear in normal computation, because the

 interpreter raises an exception instead.

 I just ran a calculation that created a NaN, the same as 4 - 3 creates a 1,
 and no exception was raised.

 Do you have an example where one is?

The math module functions raise exceptions instead of returning NaN.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ian Kelly
On Tue, Jul 8, 2014 at 12:54 PM, Anders J. Munch 2...@jmunch.dk wrote:

 Ian Kelly wrote:

 As far as I know nothing changed between 2.4 and 2.7 in this regard.
 Python has always had NaN compare unequal to everything, per the
 standard.

 It might have been platform-specific in 2.4.

I doubt it, but okay, which platform?

 Okay, here's your problem: there isn't just one binary representation
 for NaN.

 I'm fully aware of that. Whether NaN's are one equivalence class or several
 is not the issue. What matters is the integrity of the equivalence relation.

I have some bad news for you.  This is on Python 2.7.6:

 from decimal import Decimal
 from fractions import Fraction
 Decimal(2) == 2
True
 2 == Fraction(2)
True
 Decimal(2) == Fraction(2)
False

I'm not sure exactly when this bug was fixed, but it works as expected in 3.4.0.


 Following the standard isn't a good reason itself?

 If a standard tells you to jump of a cliff...

So I don't know of a good use case for nan != nan in Python (but
really I'm not the one to ask), but I do know of use cases in other
scenarios.  On platforms that don't provide an isnan() function, the
only convenient and efficient way to test for nan is by testing
reflexivity: x != x.

Following the standard means that any algorithm that uses this trick
can (in theory) be implemented in Python without changes.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ethan Furman

On 07/08/2014 12:50 PM, Ian Kelly wrote:

On Tue, Jul 8, 2014 at 1:16 PM, Ethan Furman et...@stoneleaf.us wrote:

What you said is: They just don't appear in normal computation, because the

interpreter raises an exception instead.

I just ran a calculation that created a NaN, the same as 4 - 3 creates a 1,
and no exception was raised.

Do you have an example where one is?


The math module functions raise exceptions instead of returning NaN.


Ah, so if actual numbers go in, either actual numbers come out or an exception is raised -- good to know, and thanks for 
clarifying.


--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ethan Furman

On 07/08/2014 11:54 AM, Anders J. Munch wrote:


If a standard tells you to jump of a cliff...


because a bunch of tanks are chasing you down, there's water at the bottom, and 
not a helicopter in sight...

well, jumping off the cliff could easily be your best chance.  ;)

--
~Ethan~
--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Ian Kelly
On Tue, Jul 8, 2014 at 4:03 PM, Ethan Furman et...@stoneleaf.us wrote:
 On 07/08/2014 11:54 AM, Anders J. Munch wrote:


 If a standard tells you to jump of a cliff...


 because a bunch of tanks are chasing you down, there's water at the bottom,
 and not a helicopter in sight...

 well, jumping off the cliff could easily be your best chance.  ;)

Especially if you have a friend with a TARDIS.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Mark Lawrence

On 08/07/2014 23:07, Ian Kelly wrote:

On Tue, Jul 8, 2014 at 4:03 PM, Ethan Furman et...@stoneleaf.us wrote:

On 07/08/2014 11:54 AM, Anders J. Munch wrote:



If a standard tells you to jump of a cliff...



because a bunch of tanks are chasing you down, there's water at the bottom,
and not a helicopter in sight...

well, jumping off the cliff could easily be your best chance.  ;)


Especially if you have a friend with a TARDIS.



This can lead to unforeseen circumstances though 
http://en.wikipedia.org/wiki/The_Flipside_of_Dominick_Hide


--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 21:02:09 +0200, Anders J. Munch wrote:

 Steven D'Aprano wrote:
 Oh, you've read the IEEE-754 standard, and that's what it says? We're
 going to specify this behaviour for NANs just to annoy people perhaps?
 I was referring to the deliberate choice to enforce IEEE-754 rules in
 Python. There is no force of law that requires Python to do so.

There's no force of law that requires Python to enforce reflexivity on 
values where reflexivity does not apply, any more than Python should 
enforce total order on values which aren't ordered (such as complex 
numbers, or sets).

I'm sorry that you happened to (apparently) have a use-case where you 
simultaneously have to deal with NANs but not in a numeric context. But 
from the description of your problem, it seems to me that the obvious 
solution is not to deal with floats until as late as possible. That is, 
your current work-flow (if I have understood it correctly) is:

* gather unpacked floats from some device, as ints
* pack them into floats
* process them in some way which requires reflexivity
* (maybe) much later perform numeric calculations on them


It seems to me that the trivial work-around is:

* gather packed floats from some device, as ints
* process them *as ints* in some way which requires reflexivity
* unpack back into floats
* (maybe) much later perform numeric calculations on them


Although perhaps I don't understand your use-case.


-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 13:50:06 -0600, Ian Kelly wrote:

 The math module functions raise exceptions instead of returning NaN.

That's not the only way that NANs can be constructed. In particular, the 
OP is collecting NANs from some other device. I don't know how it ends up 
with NANs, but it does, so he has to deal with them.


-- 
Steven 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Steven D'Aprano
On Tue, 08 Jul 2014 13:57:30 -0600, Ian Kelly wrote:

 Decimal(2) == Fraction(2)
 False
 
 I'm not sure exactly when this bug was fixed, but it works as expected
 in 3.4.0.

It isn't a bug, it's a missing feature. The problem is that in Python 
2.7, neither Decimal nor Fraction are aware of the other:

py Decimal(2).__eq__(Fraction(2))
NotImplemented
py Fraction(2).__eq__(Decimal(2))
NotImplemented


The obvious, but wrong, solution is to coerce both into floats:

py a = Decimal(2.01)
py b = Fraction(2) - Fraction(1, 2)**100
py a  2  b  # a and b are certainly not equal
True
py float(a) == float(b)
True

Some time by Python 3.3, Decimal appears to have become aware of how to 
compare exactly with Fraction.


-- 
Steven
-- 
https://mail.python.org/mailman/listinfo/python-list


[OT] Grandma, is that you? [was Re: NaN comparisons - Call For Anecdotes]

2014-07-08 Thread Steven D'Aprano
On Wed, 09 Jul 2014 00:21:22 +0100, Mark Lawrence wrote:

 This can lead to unforeseen circumstances though
 http://en.wikipedia.org/wiki/The_Flipside_of_Dominick_Hide


I prefer this one:

http://en.wikipedia.org/wiki/Roswell_That_Ends_Well



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Terry Reedy

On 7/8/2014 8:10 PM, Steven D'Aprano wrote:


There's no force of law that requires Python to enforce reflexivity on
values where reflexivity does not apply,


There are laws of logic that make the lack of reflexivity obnoxious when 
putting objects in collections. Python evaded the problem, at least for 
some builtins, by contradicting itself and treating nans as equal to 
themselves in the context of collections.


In 2.x, 'in' was defined in terms of ==, but
 nan=float('nan')
 nl = [nan]
 nan in nl
True
even though nan != the only member of nl.

In 3.x, 'in' was redefined to include 'is' as well as '=='.

--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: NaN comparisons - Call For Anecdotes

2014-07-08 Thread Gregory Ewing

Ian Kelly wrote:


well, jumping off the cliff could easily be your best chance.  ;)


Especially if you have a friend with a TARDIS.


Or you're James Bond, in which case you ski off the
cliff and then open your parachute.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list