Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #6498 > unrolled thread
| Started by | MRAB <python@mrabarnett.plus.com> |
|---|---|
| First post | 2011-05-29 00:41 +0100 |
| Last post | 2011-05-29 21:49 -0700 |
| Articles | 17 on this page of 37 — 12 participants |
Back to article view | Back to comp.lang.python
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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2011-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Nobody <nobody@nowhere.com> |
|---|---|
| Date | 2011-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Grant Edwards <invalid@invalid.invalid> |
|---|---|
| Date | 2011-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]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2011-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2011-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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Erik Max Francis <max@alcyone.com> |
|---|---|
| Date | 2011-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]
| From | Grant Edwards <invalid@invalid.invalid> |
|---|---|
| Date | 2011-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]
| From | Chris Torek <nospam@torek.net> |
|---|---|
| Date | 2011-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]
| From | Raymond Hettinger <python@rcn.com> |
|---|---|
| Date | 2011-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