Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #6498 > unrolled thread

float("nan") in set or as key

Started byMRAB <python@mrabarnett.plus.com>
First post2011-05-29 00:41 +0100
Last post2011-05-29 21:49 -0700
Articles 17 on this page of 37 — 12 participants

Back to article view | Back to comp.lang.python


Contents

  float("nan") in set or as key MRAB <python@mrabarnett.plus.com> - 2011-05-29 00:41 +0100
    Re: float("nan") in set or as key Erik Max Francis <max@alcyone.com> - 2011-05-28 17:16 -0700
    Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-29 00:26 +0000
    Re: float("nan") in set or as key Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-05-29 13:04 +1200
      Re: float("nan") in set or as key John Nagle <nagle@animats.com> - 2011-05-28 23:12 -0700
        Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-29 10:29 +0000
          Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-05-29 22:19 +0100
            Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-05-29 23:31 +0000
              Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-01 21:41 +0100
                Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-02 09:54 +0000
                  Re: float("nan") in set or as key Grant Edwards <invalid@invalid.invalid> - 2011-06-02 13:05 +0000
                    Re: float("nan") in set or as key Robert Kern <robert.kern@gmail.com> - 2011-06-02 12:04 -0500
                  Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-02 21:47 +0100
                    Re: float("nan") in set or as key Grant Edwards <invalid@invalid.invalid> - 2011-06-03 14:52 +0000
                      Re: float("nan") in set or as key Chris Torek <nospam@torek.net> - 2011-06-03 17:52 +0000
                        Re: float("nan") in set or as key Grant Edwards <invalid@invalid.invalid> - 2011-06-06 13:54 +0000
                      Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-04 00:29 +0100
                        Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-04 09:51 +1000
                        Re: float("nan") in set or as key rusi <rustompmody@gmail.com> - 2011-06-04 00:52 -0700
                          Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-04 20:29 +0100
                        Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-05 07:21 +0000
                          Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-05 19:15 +0100
                            Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-06 00:55 +0000
                              Re: float("nan") in set or as key Nobody <nobody@nowhere.com> - 2011-06-06 23:14 +0100
                                Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-06 23:44 +0000
                                  Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-07 11:00 +1000
                        Re: float("nan") in set or as key Grant Edwards <invalid@invalid.invalid> - 2011-06-06 14:03 +0000
                  Re: float("nan") in set or as key Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-06-03 11:17 +1200
                    Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-03 04:23 +0000
                      Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-03 14:35 +1000
                        Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-03 05:59 +0000
                      Re: float("nan") in set or as key Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2011-06-04 12:14 +1200
                        Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-04 02:21 +0000
                        Re: float("nan") in set or as key Erik Max Francis <max@alcyone.com> - 2011-06-05 00:27 -0700
            Re: float("nan") in set or as key Grant Edwards <invalid@invalid.invalid> - 2011-06-01 21:01 +0000
        Re: float("nan") in set or as key Chris Torek <nospam@torek.net> - 2011-05-30 00:02 +0000
    Re: float("nan") in set or as key Raymond Hettinger <python@rcn.com> - 2011-05-29 21:49 -0700

Page 2 of 2 — ← Prev page 1 [2]


#7037

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-05 07:21 +0000
Message-ID<4deb2e65$0$29996$c3e8da3$5496439d@news.astraweb.com>
In reply to#6981
On Sat, 04 Jun 2011 00:29:10 +0100, Nobody wrote:

> If you're "fluent" in IEEE-754, then you won't find its behaviour
> unexpected. OTOH, if you are approach the issue without preconceptions,
> you're likely to notice that you effectively have one exception
> mechanism for floating-point and another for everything else.

Returning a sentinel meaning "an exceptional event occurred" is hardly 
unusual, even in Python. str.find() does is, as does re.search() and 
re.match().

In any case, nobody says that NANs should replace exceptions for floats, 
least of all the standard.


[...]
> As for IEEE-754 saying that it's [NAN == NAN] True: they only really
> had two choices: either it's True or it's False.

Incorrect. They could have specified that it was an error, like dividing 
by zero, but they didn't. Instead, the standard specifies that there are 
four mutually exclusive relationships possible:

greater than
less than
equal 
unordered

and that comparisons should either return a code identifying the 
relationship, or a True/False value. The standard allows for order 
comparisons less_than(x, y) etc. in both signalling and quiet forms.

See section 7.11 of 
http://www.validlab.com/754R/drafts/archive/2006-10-04.pdf

(the most recent draft of the 2008 standard I can find without paying for 
the official standard).


> NaNs provide "exceptions" even if the
> hardware or the language lacks them, but that falls down once you leave
> the scope of floating-point. It wouldn't have been within IEEE-754's
> ambit to declare that comparing NaNs should return NaB (Not A Boolean).

Of course it would have been. That's effectively what the standard 
actually does. Not "Not A Bool" per se, but comparisons can return 
"Unordered", or they can signal.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#7053

FromNobody <nobody@nowhere.com>
Date2011-06-05 19:15 +0100
Message-ID<pan.2011.06.05.18.14.58.407000@nowhere.com>
In reply to#7037
On Sun, 05 Jun 2011 07:21:10 +0000, Steven D'Aprano wrote:

> Returning a sentinel meaning "an exceptional event occurred" is hardly 
> unusual, even in Python. str.find() does is, as does re.search() and 
> re.match().

These are not "exceptional" conditions; if they were, an exception would
be used.

E.g. dict supports both d.get(key) and d[key] for lookups. The former
returns a sentinel, the latter raises an exception. The latter makes sense
if you "expect" the key to be present, the former if you don't.

>> As for IEEE-754 saying that it's [NAN == NAN] True: they only really
>> had two choices: either it's True or it's False.
> 
> Incorrect. They could have specified that it was an error, like dividing 
> by zero, but they didn't.

Specifying an error doesn't remove the requirement to also specify a
result. E.g. dividing a finite value by zero produces a result of
infinity. In languages which lack exceptions, errors only matter if the
code bothers to check for them (if such checks are even possible; C89
lacks <fenv.h>).

[toc] | [prev] | [next] | [standalone]


#7064

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-06 00:55 +0000
Message-ID<4dec2575$0$29996$c3e8da3$5496439d@news.astraweb.com>
In reply to#7053
On Sun, 05 Jun 2011 19:15:02 +0100, Nobody wrote:

> On Sun, 05 Jun 2011 07:21:10 +0000, Steven D'Aprano wrote:
> 
>> Returning a sentinel meaning "an exceptional event occurred" is hardly
>> unusual, even in Python. str.find() does is, as does re.search() and
>> re.match().
> 
> These are not "exceptional" conditions; if they were, an exception would
> be used.


Exceptional does not mean rare or unexpected. Searching for a substring 
returns the offset of that substring. If it is not found, that's the 
exceptional case.

str.index raises an exception, and str.find returns a sentinel:

>>> "spam".index("z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found
>>> "spam".find("z")
-1



>>> As for IEEE-754 saying that it's [NAN == NAN] True: they only really
>>> had two choices: either it's True or it's False.
>> 
>> Incorrect. They could have specified that it was an error, like
>> dividing by zero, but they didn't.
> 
> Specifying an error doesn't remove the requirement to also specify a
> result.

Untrue, but irrelevant. (Standards often allow implementation-dependent 
behaviour.) The standard *could* have said that NAN == NAN be an error, 
but *didn't*, so what it should or shouldn't have done if it were an 
error is irrelevant, because it's not an error.

And thus we come back full circle. Hundreds of words, and I'm still no 
closer to understanding why you think that "NAN == NAN" should be an 
error.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#7112

FromNobody <nobody@nowhere.com>
Date2011-06-06 23:14 +0100
Message-ID<pan.2011.06.06.22.14.07.563000@nowhere.com>
In reply to#7064
On Mon, 06 Jun 2011 00:55:18 +0000, Steven D'Aprano wrote:

> And thus we come back full circle. Hundreds of words, and I'm still no 
> closer to understanding why you think that "NAN == NAN" should be an 
> error.

Well, you could try improving your reading comprehension. Counselling
might help.

AFAICT, your main problem is that you can't distinguish between not
agreeing with a particular argument and being unable to even recognise
the existence of the argument.

A really big clue is here:

> why you think that "NAN == NAN" should be an error

Given that my very first comment in the thread was:

> > Wrong.
> 
> That's overstating it. There's a good argument to be made for ...

I never said that it /should/ be an error, and later explicitly stated
that I wasn't arguing for it but pointing out that it's /arguable/.

But you appear unable to comprehend such distinctions. Don't agree with
the argument, don't accept the argument, don't recognise that there is an
argument; these all appear to be the same thing.

[toc] | [prev] | [next] | [standalone]


#7116

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-06 23:44 +0000
Message-ID<4ded6646$0$29996$c3e8da3$5496439d@news.astraweb.com>
In reply to#7112
On Mon, 06 Jun 2011 23:14:15 +0100, Nobody wrote:

> On Mon, 06 Jun 2011 00:55:18 +0000, Steven D'Aprano wrote:
> 
>> And thus we come back full circle. Hundreds of words, and I'm still no
>> closer to understanding why you think that "NAN == NAN" should be an
>> error.
> 
> Well, you could try improving your reading comprehension. Counselling
> might help.

Thank you for your concern about my mental health.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#7124

FromChris Angelico <rosuav@gmail.com>
Date2011-06-07 11:00 +1000
Message-ID<mailman.2513.1307408454.9059.python-list@python.org>
In reply to#7116
On Tue, Jun 7, 2011 at 9:44 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Thank you for your concern about my mental health.

Mental health? You're a programmer. It's far too late to worry about that.

My name is Chris, and I'm a programmer. It started when I was just a
child - my parents thought it would be alright for me to get into
these sorts of things. Kept me busy when they wanted to work. But it
grew from there. I was programming after school; I was programming
instead of going to bed. My social life deteriorated until I found I
was more interested in programming than in going to parties. When I
found myself writing programs during dinner, I knew I was an addict.
So I came to Prog-Anon, with their 12-step ...... ARGH! I can't
escape!!

Chris Angelico

[toc] | [prev] | [next] | [standalone]


#7085

FromGrant Edwards <invalid@invalid.invalid>
Date2011-06-06 14:03 +0000
Message-ID<isimnq$1ic$2@reader1.panix.com>
In reply to#6981
On 2011-06-03, Nobody <nobody@nowhere.com> wrote:

>>> This would produce the same end result as raising an exception
>>> immediately, but would reduce the number of isnan() tests.
>> 
>> I've never found the number of isnan() checks in my code to be an
>> issue -- there just arent that many of them, and when they are there,
>> it provides an easy to read and easy to maintain way to handle things.
>
> I think that you misunderstood. What I was saying here was that, if you
> wanted exception-on-NaN behaviour from Python, the interpreter wouldn't
> need to call isnan() on every value received from the FPU, but rely upon
> NaN-propagation and only call it at places where a NaN might disappear
> (e.g. comparisons).

Ideed, I did misunderstand.  I thought you were talking about a
the value of reducing the number of isnan() tests in user application
code.

>>> I mean undefined, in the sense that 0/0 is undefined
>> 
>> But 0.0/0.0 _is_ defined.  It's NaN.  ;)
>
> Mathematically, it's undefined.

True, but we must be careful not to confuse math and scientific
calculation using fixed-length binary floting point.

>> IMHO, that's a bug.  IEEE-754 states explicit that 0.0/0.0 is NaN.
>> Pythons claims it implements IEEE-754.  Python got it wrong.
>
> But then IEEE-754 considers integers and floats to be completely
> different beasts, while Python makes some effort to maintain a
> unified "numeric" interface. If you really want IEEE-754
> to-the-letter, that's undesirable, although I'd question the choice
> of Python in such situations.

Python's minor issues with IEEE-754 are far outweighed by advantages
in other areas. :)

>>> If anything, it has proven to be a major nuisance. It takes a lot of
>>> effort to create (or even specify) code which does the right thing in
>>> the presence of NaNs.
>> 
>> That's not been my experience.  NaNs save a _huge_ amount of effort
>> compared to having to pass value+status info around throughout
>> complex caclulations.
>
> That's what exceptions are for. NaNs probably save a huge amount of
> effort in languages which lack exceptions, but that isn't applicable
> to Python.

How do you obtain using exceptions a behavior that's the same as with
quiet NaNs?

>>>> The correct answer to "nan == nan" is to raise an exception,
>>>> because you have asked a question for which the answer is nether True
>>>> nor False.
>>> 
>>> Wrong.
>>
>> That's overstating it. 

It was an attempt to illustate the overstatement to which it was a
reply.

-- 
Grant Edwards               grant.b.edwards        Yow! You should all JUMP
                                  at               UP AND DOWN for TWO HOURS
                              gmail.com            while I decide on a NEW
                                                   CAREER!!

[toc] | [prev] | [next] | [standalone]


#6894

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2011-06-03 11:17 +1200
Message-ID<94qjvvFb02U1@mid.individual.net>
In reply to#6848
Steven D'Aprano wrote:

> def kronecker(x, y):
>     if x == y: return 1
>     return 0
> 
> This will correctly consume NAN arguments. If either x or y is a NAN, it 
> will return 0.

I'm far from convinced that this result is "correct". For one
thing, the Kronecker delta is defined on integers, not reals,
so expecting it to deal with NaNs at all is nonsensical.
For another, this function as written is numerically suspect,
since it relies on comparing floats for exact equality.

But the most serious problem is, given that

> NAN is a sentinel for an invalid operation. NAN + NAN returns a NAN 
> because it is an invalid operation,

if kronecker(NaN, x) or kronecker(x, Nan) returns anything
other than NaN or some other sentinel value, then you've
*lost* the information that an invalid operation occurred
somewhere earlier in the computation.

You can't get a valid result from data produced by an
invalid computation. Garbage in, garbage out.

> not because NANs are magical goop that spoil everything they touch.

But that's exactly how the *have* to behave if they truly
indicate an invalid operation.

SQL has been mentioned in relation to all this. It's worth
noting that the result of comparing something to NULL in
SQL is *not* true or false -- it's NULL!

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#6912

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-03 04:23 +0000
Message-ID<4de861ae$0$29985$c3e8da3$5496439d@news.astraweb.com>
In reply to#6894
On Fri, 03 Jun 2011 11:17:17 +1200, Gregory Ewing wrote:

> Steven D'Aprano wrote:
> 
>> def kronecker(x, y):
>>     if x == y: return 1
>>     return 0
>> 
>> This will correctly consume NAN arguments. If either x or y is a NAN,
>> it will return 0.
> 
> I'm far from convinced that this result is "correct". For one thing, the
> Kronecker delta is defined on integers, not reals, so expecting it to
> deal with NaNs at all is nonsensical. 

Fair point. Call it an extension of the Kronecker Delta to the reals then.


> For another, this function as
> written is numerically suspect, since it relies on comparing floats for
> exact equality.

Well, it is a throw away function demonstrating a principle, not battle-
hardened production code.

But it's hard to say exactly what alternative there is, if you're going 
to accept floats. Should you compare them using an absolute error? If so, 
you're going to run into trouble if your floats get large. It is very 
amusing when people feel all virtuous for avoiding equality and then 
inadvertently do something like this:

y = 2.1e12
if abs(x - y) <= 1e-9:
    # x is equal to y, within exact tolerance
    ...

Apart from being slower and harder to read, how is this different from 
the simpler, more readable x == y?

What about a relative error? Then you'll get into trouble when the floats 
are very small. And how much error should you accept? What's good for 
your application may not be good for mine.

Even if you define your equality function to accept some limited error 
measured in Units in Last Place (ULP), "equal to within 2 ULP" (or any 
other fixed tolerance) is no better, or safer, than exact equality, and 
very likely worse.

In practice, either the function needs some sort of "how to decide 
equality" parameter, so the caller can decide what counts as equal in 
their application, or you use exact floating point equality and leave it 
up to the caller to make sure the arguments are correctly rounded so that 
values which should compare equal do compare equal.


> But the most serious problem is, given that
> 
>> NAN is a sentinel for an invalid operation. NAN + NAN returns a NAN
>> because it is an invalid operation,
> 
> if kronecker(NaN, x) or kronecker(x, Nan) returns anything other than
> NaN or some other sentinel value, then you've *lost* the information
> that an invalid operation occurred somewhere earlier in the computation.

If that's the most serious problem, then I'm laughing, because of course 
I haven't lost anything.

x = result_of_some_computation(a, b, c)  # may return NAN
y = kronecker(x, 42)

How have I lost anything? I still have the result of the computation in 
x. If I throw that value away, it is because I no longer need it. If I do 
need it, it is right there, where it always was.

You seem to have fallen for the myth that NANs, once they appear, may 
never disappear. This is a common, but erroneous, misapprehension, e.g.:

    "NaN is like a trap door that once you have fallen in you cannot
     come back out. Otherwise, the possibility exists that a calculation
     will have gone off course undetectably."

http://www.rhinocerus.net/forum/lang-fortran/94839-fortran-ieee-754-
maxval-inf-nan-2.html#post530923

Certainly if you, the function writer, has any reasonable doubt about the 
validity of a NAN input, you should return a NAN. But that doesn't mean 
that NANs are "trap doors". It is fine for them to disappear *if they 
don't matter* to the final result of the calculation. I quote:

    "The key result of these rules is that once you get a NaN during 
     a computation, the NaN has a STRONG TENDENCY [emphasis added] to
     propagate itself throughout the rest of the computation..."

http://www.savrola.com/resources/NaN.html

Another couple of good examples:

- from William Kahan, and the C99 standard: hypot(INF, x) is always INF 
regardless of the value of x, hence hypot(INF, NAN) returns INF.

- since pow(x, 0) is always 1 regardless of the value of x, pow(NAN, 0) 
is also 1.

In the case of the real-valued Kronecker delta, I argue that the NAN 
doesn't matter, and it is reasonable to allow it to disappear.

Another standard example where NANs get thrown away is the max and min 
functions. The latest revision of IEEE-754 (2008) allows for max and min 
to ignore NANs.

 
> You can't get a valid result from data produced by an invalid
> computation. Garbage in, garbage out.

Of course you can. Here's a trivial example:

def f(x):
    return 1

It doesn't matter what value x takes, the result of f(x) should be 1. 
What advantage is there in having f(NAN) return NAN? 


>> not because NANs are magical goop that spoil everything they touch.
> 
> But that's exactly how the *have* to behave if they truly indicate an
> invalid operation.
> 
> SQL has been mentioned in relation to all this. It's worth noting that
> the result of comparing something to NULL in SQL is *not* true or false
> -- it's NULL!

I'm sure they have their reasons for that. Whether they are good reasons 
or not, I don't know. I do know that the 1999 SQL standard defined *four* 
results for boolean comparisons, true/false/unknown/null, but allowed 
implementations to treat unknown and null as the same.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#6914

FromChris Angelico <rosuav@gmail.com>
Date2011-06-03 14:35 +1000
Message-ID<mailman.2416.1307075755.9059.python-list@python.org>
In reply to#6912
On Fri, Jun 3, 2011 at 2:23 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
>> You can't get a valid result from data produced by an invalid
>> computation. Garbage in, garbage out.
>
> Of course you can. Here's a trivial example:
>
> def f(x):
>    return 1
>

If your incoming x is garbage, your outgoing 1 is also garbage. Later
on, you can use 'isgarbage(x)' to find out whether anything went
wrong. You can also use 'isinsane(self)', which is defined as follows:

class Programmer:
  def isinsane(self):
    return True if float("nan")==float("nan") else True

Chris Angelico

[toc] | [prev] | [next] | [standalone]


#6915

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-03 05:59 +0000
Message-ID<4de87835$0$29996$c3e8da3$5496439d@news.astraweb.com>
In reply to#6914
On Fri, 03 Jun 2011 14:35:52 +1000, Chris Angelico wrote:

> On Fri, Jun 3, 2011 at 2:23 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>>> You can't get a valid result from data produced by an invalid
>>> computation. Garbage in, garbage out.
>>
>> Of course you can. Here's a trivial example:
>>
>> def f(x):
>>    return 1
>>
>>
> If your incoming x is garbage, your outgoing 1 is also garbage.

If there were non-garbage input where f(x) would return something other 
than 1, then you might argue that "well, we can't be sure what value 
f(x) should return, so we better return a NAN". But there is no such 
input.

NANs are a tool, not poison. They indicate an invalid calculation. Not 
all calculations are critical. What do you do when you reach an invalid 
calculation and you can't afford to just give up and halt the program 
with an error? You try to fix it with another calculation!

If you're in the fortunate situation that you can say "this bad input 
does not matter", then *that input does not matter*. Regardless of 
whether your input is a NAN, or you've just caught an exception, you have 
the opportunity to decide what the appropriate response is.

You might not be able to fix the situation, in which case it is 
appropriate to return a NAN to signal to the next function that you don't 
have a valid result. But sometimes one bad value is not the end of the 
world. Perhaps you try again with a smaller step size, or you skip this 
iteration of the calculation, or you throw away the current value and 
start again from a different starting point, or do whatever is needed to 
get the result you want.

In the case of my toy function, whatever is needed is... nothing at all. 
Just return 1, the same as you would for any other input, because the 
input literally does not matter for the output.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#6985

FromGregory Ewing <greg.ewing@canterbury.ac.nz>
Date2011-06-04 12:14 +1200
Message-ID<94tbmeF41kU1@mid.individual.net>
In reply to#6912
Steven D'Aprano wrote:
> Fair point. Call it an extension of the Kronecker Delta to the reals then.

That's called the Dirac delta function, and it's a bit different --
instead of a value of 1, it has an infinitely high spike of zero
width at the origin, whose integral is 1. (Which means it's not
strictly a function, because it's impossible for a true function
on the reals to have those properties.)

You don't normally use it on its own; usually it turns up as part
of an integral. I find it difficult to imagine a numerical algorithm
that relies on directly evaluating it. Such an algorithm would be
numerically unreliable. You just wouldn't do it that way; you'd
find some other way to calculate the integral that avoids evaluating
the delta.

> y = 2.1e12
> if abs(x - y) <= 1e-9:
>     # x is equal to y, within exact tolerance
>     ...

If you expect your numbers to be on the order of 1e12, then 1e-9
is obviously not a sensible choice of tolerance. You don't just
pull tolerances out of thin air, you justify them based on
knowledge of the problem at hand.

> In practice, either the function needs some sort of "how to decide 
> equality" parameter,

If it's general purpose library code, then yes, that's exactly
what it needs.

> or you use exact floating point equality and leave it 
> up to the caller to make sure the arguments are correctly rounded

Not really a good idea. Trying to deal with this kind of thing
by rounding is fraught with difficulties and pitfalls. It can
only work when you're not really using floats as approximations
of reals, but as some set of discrete values, in which case
it's probably safer to use appropriately-scaled integers.

> - from William Kahan, and the C99 standard: hypot(INF, x) is always INF 
> regardless of the value of x, hence hypot(INF, NAN) returns INF.
> 
> - since pow(x, 0) is always 1 regardless of the value of x, pow(NAN, 0) 
> is also 1.

These are different from your kronecker(), because the result
*never* depends on the value of x, whether it's NaN or not.
But kronecker() clearly does depend on the value of x sometimes.

The reasoning appears to be based on the idea that NaN means
"some value, we just don't know what it is". Accepting that
interpretation, the argument doesn't apply to kronecker().
You can't say that the NaN in kronecker(NaN, 42) doesn't
matter, because if you don't know what value it represents,
you can't be sure that it *isn't* meant to be 42.

> Another standard example where NANs get thrown away is the max and min 
> functions. The latest revision of IEEE-754 (2008) allows for max and min 
> to ignore NANs.

Do they provide a justification for that? I'm having trouble
seeing how it makes sense.

-- 
Greg

[toc] | [prev] | [next] | [standalone]


#6992

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-06-04 02:21 +0000
Message-ID<4de996ab$0$29996$c3e8da3$5496439d@news.astraweb.com>
In reply to#6985
On Sat, 04 Jun 2011 12:14:03 +1200, Gregory Ewing wrote:

> Steven D'Aprano wrote:
>> Fair point. Call it an extension of the Kronecker Delta to the reals
>> then.
> 
> That's called the Dirac delta function, and it's a bit different 

Yes, I'm familiar with the Dirac delta. As you say, it's not really 
relevant to the question on hand.

In any case, my faux Kronecker was just a throw away example. If you 
don't like it, throw it away! The specific example doesn't matter, since 
the principle applies: functions may throw away NANs if they are not 
relevant to the calculation. The presence of a NAN is not intended to be 
irreversible, merely *usually* irreversible.


[...]
>> y = 2.1e12
>> if abs(x - y) <= 1e-9:
>>     # x is equal to y, within exact tolerance ...
> 
> If you expect your numbers to be on the order of 1e12, then 1e-9 is
> obviously not a sensible choice of tolerance. You don't just pull
> tolerances out of thin air, you justify them based on knowledge of the
> problem at hand.

Exactly. But that's precisely what people do! Hence my comment (which you 
snipped) about people feeling virtuous because they avoid "testing floats 
for equality", but then they go and do an operation like the above.

I'm sure you realise this, but for anyone reading who doesn't understand 
why the above is silly, there are no floats less than 1e-9 from y above.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#7038

FromErik Max Francis <max@alcyone.com>
Date2011-06-05 00:27 -0700
Message-ID<PZednTg04OZ7snbQnZ2dnUVZ5qKdnZ2d@giganews.com>
In reply to#6985
Gregory Ewing wrote:
> Steven D'Aprano wrote:
>> Fair point. Call it an extension of the Kronecker Delta to the reals 
>> then.
> 
> That's called the Dirac delta function, and it's a bit different --
> instead of a value of 1, it has an infinitely high spike of zero
> width at the origin, whose integral is 1. (Which means it's not
> strictly a function, because it's impossible for a true function
> on the reals to have those properties.)
> 
> You don't normally use it on its own; usually it turns up as part
> of an integral. I find it difficult to imagine a numerical algorithm
> that relies on directly evaluating it. Such an algorithm would be
> numerically unreliable. You just wouldn't do it that way; you'd
> find some other way to calculate the integral that avoids evaluating
> the delta.

True, but that's the Dirac delta, which as you (and later he) said, is 
quite a different thing, not simply a Kronecker delta extended to the 
reals.  Kronecker deltas are used all the time over the reals; for 
instance, in tensor calculus.  Just because the return values are either 
0 or 1 doesn't mean that their use is incompatible over reals (as 
integers are subsets of reals).

-- 
Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
  San Jose, CA, USA && 37 18 N 121 57 W && AIM/Y!M/Skype erikmaxfrancis
   It is a rough road that leads to the heights of greatness.
    -- Seneca, 4 BC-65 AD

[toc] | [prev] | [next] | [standalone]


#6827

FromGrant Edwards <invalid@invalid.invalid>
Date2011-06-01 21:01 +0000
Message-ID<is69b3$pnc$1@reader1.panix.com>
In reply to#6578
On 2011-05-29, Nobody <nobody@nowhere.com> wrote:
> On Sun, 29 May 2011 10:29:28 +0000, Steven D'Aprano wrote:
>
>>> The correct answer to "nan == nan" is to raise an exception, because
>>> you have asked a question for which the answer is nether True nor
>>> False.
>> 
>> Wrong.
>
> That's overstating it. There's a good argument to be made for raising
> an exception. Bear in mind that an exception is not necessarily an
> error, just an "exceptional" condition.
>
>> The correct answer to "nan == nan" is False, they are not equal.
>
> There is no correct answer to "nan == nan".

For those of us who have to deal with the real world (that means
complying with IEEE-754), there _is_ a correct answer.  IIRC, the IEEE
standard requires nan == nan is false, and nan != nan is true.

That said, I don't remember what the other comparisons are supposed to
do...

> Defining it to be false is just the "least wrong" answer.
>
> Arguably, "nan != nan" should also be false, but that would violate
> the invariant "(x != y) == !(x == y)".

And it would violate the IEEE standard.  IEEE-754 has it's warts, but
we're far better off than we were with dozens of incompatible,
undocumented, vendor-specific schemes (most of which had more warts
than IEEE-754).

-- 
Grant Edwards               grant.b.edwards        Yow! I'm dressing up in
                                  at               an ill-fitting IVY-LEAGUE
                              gmail.com            SUIT!!  Too late...

[toc] | [prev] | [next] | [standalone]


#6599

FromChris Torek <nospam@torek.net>
Date2011-05-30 00:02 +0000
Message-ID<irumpq08mp@news3.newsguy.com>
In reply to#6514
Incidentally, note:

    $ python
    ...
    >>> nan = float("nan")
    >>> nan
    nan
    >>> nan is nan
    True
    >>> nan == nan
    False

In article <4de1e3e7$0$2195$742ec2ed@news.sonic.net>
John Nagle  <nagle@animats.com> wrote:
>    The correct answer to "nan == nan" is to raise an exception, because
>you have asked a question for which the answer is nether True nor False.

Well, in some sense, the "correct answer" depends on which question
you *meant* to ask. :-)  Seriously, some (many?) instruction sets
have two kinds of comparison instructions: one that raises an
exception here, and one that does not.

>    The correct semantics for IEEE floating point look something like
>this:
>
>       1/0             INF
>       INF + 1         INF
>       INF - INF       NaN
>       INF == INF      unordered
>       NaN == NaN      unordered
>
>INF and NaN both have comparison semantics which return
>"unordered". The FPU sets a bit for this, which most language
>implementations ignore.

Again, this depends on the implementation.

This is similar to (e.g.) the fact that on the MIPS, there are two
different integer add instructions ("addi" and "addiu"): one
raises an overflow exception, the other performs C "unsigned"
style arithmetic (where, e.g., 0xffffffff + 1 = 0, in 32 bits).

>Python should raise an exception on unordered comparisons.
>Given that the language handles integer overflow by going to
>arbitrary-precision integers, checking the FPU status bits is
>cheap.

I could go for that myself.  But then you also need a "don't raise
exception but give me an equality test result" operator (for various
special-case purposes at least) too.  Of course a simple "classify
this float as one of normal, subnormal, zero, infinity, or NaN"
operator would suffice here (along with the usual "extract sign"
and "differentiate between quiet and signalling NaN" operations).
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: gmail (figure it out)      http://web.torek.net/torek/index.html

[toc] | [prev] | [next] | [standalone]


#6625

FromRaymond Hettinger <python@rcn.com>
Date2011-05-29 21:49 -0700
Message-ID<f4f31d9d-18ea-405e-9b71-3b376b541bd3@22g2000prx.googlegroups.com>
In reply to#6498
On May 28, 4:41 pm, MRAB <pyt...@mrabarnett.plus.com> wrote:
> Here's a curiosity. float("nan") can occur multiple times in a set or as
> a key in a dict:

Which is by design.

NaNs intentionally have multiple possible instances (some
implementations even include distinct payload values).

Sets and dicts intentionally recognize an instance as being equal to
itself (identity-implies-equality); otherwise, you could put a NaN in
a set/dict but not be able to retrieve it.  Basic invariants would
fail -- such as:  assert all(elem in container for elem in container).

The interesting thing is that people experimenting with exotic objects
(things with random hash functions, things with unusual equality or
ordering relations, etc) are "surprised" when those objects display
their exotic behaviors.

To me, the "NaN curiousities" are among the least interesting.  It's
more fun to break sort algorithms with sets (which override the
ordering relations with subset/superset relations) or with an object
that mutates a list during the sort.  Now, that is curious :-)

Also, Dr Mertz wrote a Charming Python article full of these
curiosities:
http://gnosis.cx/publish/programming/charming_python_b25.txt

IMO, equality and ordering are somewhat fundamental concepts.  If a
class is written that twists those concepts around a bit, then it
should be no surprise if curious behavior emerges.  Heck, I would
venture to guess that something as simple as assuming the speed of
light is constant might yield twin paradoxes and other
curiousities ;-)

Raymond

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web