Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On Sat, Apr 30, 2011 at 3:11 AM, Guido van Rossum gu...@python.org wrote: Decimal, for that reason, has a context that lets one specify different behaviors when a NaN is produced. Would it make sense to add a float context that also lets one specify what should happen? That could include returning Inf for 1.0/0.0 (for experts), or raising exceptions when NaNs are produced (for the numerically naive like myself). I could see a downside too, e.g. the correctness of code that passingly uses floats might be affected by the context settings. There's also the question of whether the float context should affect int operations; floats vs. ints is another can of worms since (in Python 3) we attempt to tie them together through 1/2 == 0.5, but ints have a much larger range than floats. Given that we delegate most float() behaviour to the underlying CPU and C libraries (and then the math module tries to cope with any cross-platform discrepancies), introducing context handling isn't easy, and would likely harm the current speed advantage that floats hold over the decimal module. We decided that losing the speed advantage of native integers was worthwhile in order to better unify the semantics of int and long for Py3k, but both the speed differential and the semantic gap between float() and decimal.Decimal() are significantly larger. However, I did find Terry's suggestion of using the warnings module to report some of the floating point corner cases that currently silently produce unexpected results to be an interesting one. If those operations issued a FloatWarning, then users could either silence them or turn them into errors as desired. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On 5/1/2011 7:27 AM, Nick Coghlan wrote: However, I did find Terry's suggestion of using the warnings module to report some of the floating point corner cases that currently silently produce unexpected results to be an interesting one. If those operations issued a FloatWarning, then users could either silence them or turn them into errors as desired. I would like to take credit for that, but I was actually seconding Alexander's insight and idea. I may have added the specific name after looking at the currently list and seeing UnicodeWarning and BytesWarning, so why not a FloatWarning. I did read the warnings doc more carefully to verify that it would really put the user in control, which was apparently the intent of the committee. I am not sure whether FloatWarnings should ignored or printed by default. Ignored would, I guess, match current behavior, unless something else is changed as part of a more extensive overhaul. -f and -ff are available to turn ignored FloatWarning into print or raise exception, as with BytesWarning. I suspect that these would get at lease as much usage as -b and -bb. So I see 4 questions: 1. Add FloatWarning? 2. If yes, default disposition? 3. Add command line options? 4. Use the addition of FloatWarning as an opportunity to change other defaults, given that user will have more options? -- Terry Jan Reedy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Fri, Apr 29, 2011 at 2:18 AM, Greg Ewing greg.ew...@canterbury.ac.nz wrote: Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? History, I think. There's a c.l.p. message from Tim Peters somewhere saying something along the lines that he'd love to make (e.g.,) 1e300 * 1e300 raise an exception instead of producing an infinity, but dare not for fear of the resulting outcry from people who use the current behaviour. Apologies if I've misrepresented what he actually said---I'm failing to find the exact message at the moment. If it weren't for backwards compatibility, I'd love to see Python raise exceptions instead of producing IEEE special values: IOW, to act as though the divide-by-zero, overflow and invalid_operation FP signals all produce an exception. As a bonus, perhaps there could be a mode that allowed 'nonstop' arithmetic, under which infinities and nans were produced as per IEEE 754: with math.non_stop_arithmetic(): ... But this is python-ideas territory. Mark ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Sat, 30 Apr 2011 08:02:33 +0100 Mark Dickinson dicki...@gmail.com wrote: On Fri, Apr 29, 2011 at 2:18 AM, Greg Ewing greg.ew...@canterbury.ac.nz wrote: Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? History, I think. There's a c.l.p. message from Tim Peters somewhere saying something along the lines that he'd love to make (e.g.,) 1e300 * 1e300 raise an exception instead of producing an infinity, but dare not for fear of the resulting outcry from people who use the current behaviour. Apologies if I've misrepresented what he actually said---I'm failing to find the exact message at the moment. If it weren't for backwards compatibility, I'd love to see Python raise exceptions instead of producing IEEE special values: IOW, to act as though the divide-by-zero, overflow and invalid_operation FP signals all produce an exception. As a bonus, perhaps there could be a mode that allowed 'nonstop' arithmetic, under which infinities and nans were produced as per IEEE 754: with math.non_stop_arithmetic(): ... But this is python-ideas territory. I would much prefer this idea than the idea of making NaNs non-orderable. It would break code, but at least it would break in less unexpected and annoying ways. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
[Greg Ewing] Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? [Mark Dickinson] History, I think. There's a c.l.p. message from Tim Peters somewhere saying something along the lines that he'd love to make (e.g.,) 1e300 * 1e300 raise an exception instead of producing an infinity, but dare not for fear of the resulting outcry from people who use the current behaviour. Apologies if I've misrepresented what he actually said---I'm failing to find the exact message at the moment. If it weren't for backwards compatibility, I'd love to see Python raise exceptions instead of producing IEEE special values: IOW, to act as though the divide-by-zero, overflow and invalid_operation FP signals all produce an exception. Exactly. It's impossible to create a NaN from normal inputs without triggering div-by-0 or invalid_operation, and if overflow were also enabled it would likewise be impossible to create an infinity from normal inputs. So, 20 years ago, that's how I arranged Kendall Square Research's default numeric environment: enabled those three exception traps by default, and left the underflow and inexact exception traps disabled by default. It's not just naive users initially baffled by NaNs and infinities; most of KSR's customers were heavy duty number crunchers, and they didn't know what to make of them at first either. But experts do find them very useful (after climbing the 754 learning curve), so there was also a simple function call (from all the languages we supported - C, C++, FORTRAN and Pascal), to establish the 754 default all-traps-disabled mode: As a bonus, perhaps there could be a mode that allowed 'nonstop' arithmetic, under which infinities and nans were produced as per IEEE 754: with math.non_stop_arithmetic(): ... But this is python-ideas territory. All of which is just moving toward the numeric environment 754 was aiming for from the start: complete user control over which exception traps are and aren't currently enabled. The only quibble I had with that vision was its baffle-99%-of-users requirement that they _all_ be disabled by default. As Kahan wrote, it's called an exception because no matter _what_ you do, someone will take exception to your policy ;-) That's why user control is crucial in a 754 environment. He wanted even more control than 754 recommends (in particular, he wanted the user to be able to specify _which_ value was returned when an exception triggered; e.g., in some apps it may well be more useful for overflow to produce a NaN than an infinity, or to return the largest normal value with the correct sign). Unfortunately, the hardware and academic types who created 754 had no grasp of how difficult it is to materialize their vision in software, and especially not of how very difficult it is to backstitch a pleasant wholly conforming environment into an existing language. As a result, I'm afraid the bulk of 754's features are stilled viewed as a nuisance by a vast majority of users :-( ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Steven D'Aprano st...@pearwood.info writes: Robert Kern wrote: On 4/28/11 8:44 PM, Steven D'Aprano wrote: The real question should be, why does Python treat all NANs as signalling NANs instead of quiet NANs? I don't believe this helps anyone. Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. Sorry, did I get that backwards? I thought it was signalling NANs that cause a signal (in Python terms, an exception)? If I do x = 0.0/0 I get an exception instead of a NAN. Hence a signalling NAN. Robert has interpreted your “treats all NaNs as signalling NaNs” to mean “treats all objects that Python calls a NaN as signalling NaNs”, and is pointing out that no, the objects that Python calls “NaN” are all quiet NaNs. You might be clearer if you distinguish between what Python calls a NaN and what you call a NaN. It seems you're saying that some Python exception objects (e.g. ZeroDivisionError objects) are what you call NaNs, despite the fact that they're not what Python calls a NaN. -- \ “We can't depend for the long run on distinguishing one | `\ bitstream from another in order to figure out which rules | _o__) apply.” —Eben Moglen, _Anarchism Triumphant_, 1999 | Ben Finney ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Fri, Apr 29, 2011 at 3:28 PM, Steven D'Aprano st...@pearwood.info wrote: Robert Kern wrote: Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. Sorry, did I get that backwards? I thought it was signalling NANs that cause a signal (in Python terms, an exception)? If I do x = 0.0/0 I get an exception instead of a NAN. Hence a signalling NAN. Aside from the divide-by-zero case, we treat NaNs as quiet NaNs. This is largely due to the fact float operations are delegated to the underlying CPU, and SIGFPE is ignored by default. You can fiddle with it either by building and using the fpectl module, or else by switching to decimal.Decimal() instead (which offers much finer control over signalling through its thread local context information). The latter is by far the preferable course, unless you're targeting specific hardware with well-defined FPE behaviour. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Ben Finney wrote: Steven D'Aprano st...@pearwood.info writes: Robert Kern wrote: On 4/28/11 8:44 PM, Steven D'Aprano wrote: The real question should be, why does Python treat all NANs as signalling NANs instead of quiet NANs? I don't believe this helps anyone. Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. Sorry, did I get that backwards? I thought it was signalling NANs that cause a signal (in Python terms, an exception)? If I do x = 0.0/0 I get an exception instead of a NAN. Hence a signalling NAN. Robert has interpreted your “treats all NaNs as signalling NaNs” to mean “treats all objects that Python calls a NaN as signalling NaNs”, and is pointing out that no, the objects that Python calls “NaN” are all quiet NaNs. I'm sorry for my lack of clarity. I'm referring to functions which potentially produce NANs, not the exceptions themselves. A calculation which might have produced a (quiet) NAN as the result instead raises an exception (which I'm treating as equivalent to a signal). -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Terry Reedy writes: Python treats it as if it were a number: As I said, so did the committee, and that was its mistake that we are more or less stuck with. The committee didn't really have a choice. You could ask that they call NaNs something else, but some bit pattern is going to appear in the result register after each computation, and further operations may (try to) use that bit pattern. Seems reasonable to me to apply duck- typing and call those patterns numbers for the purpose of IEEE 754, and to define them in such a way that operating on them produces a non-NaN only when *all* numbers (including infinity) produce the same non-NaN. The alternative is to raise an exception whenever a NaN would be generated (but something is still going to appear in the register; I don't know any number that should be put there, do you?) That is excessively punishing to Python users and programmers, though, since Python handles exceptions by terminating the computation. (Kahan points out that signaling NaNs are essentially never used for this reason.) Other aspects of NaN behavior may be a mistake. But it's not clear to me, even after all the discussion in this thread. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Steven D'Aprano st...@pearwood.info writes: I'm sorry for my lack of clarity. I'm referring to functions which potentially produce NANs, not the exceptions themselves. A calculation which might have produced a (quiet) NAN as the result instead raises an exception (which I'm treating as equivalent to a signal). Yes, it produces a Python exception, which is not a Python NaN. If you want to talk about “signalling NaNs”, you'll have to distinguish that (every time!) so you're not misunderstood as referring to a Python NaN object. -- \ “It's my belief we developed language because of our deep inner | `\ need to complain.” —Jane Wagner, via Lily Tomlin | _o__) | Ben Finney ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On 4/29/11 1:35 AM, Nick Coghlan wrote: On Fri, Apr 29, 2011 at 3:28 PM, Steven D'Apranost...@pearwood.info wrote: Robert Kern wrote: Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. Sorry, did I get that backwards? I thought it was signalling NANs that cause a signal (in Python terms, an exception)? If I do x = 0.0/0 I get an exception instead of a NAN. Hence a signalling NAN. Aside from the divide-by-zero case, we treat NaNs as quiet NaNs. And in fact, 0.0/0.0 is covered by the more general rule that x/0.0 raises ZeroDivisionError, not a rule that converts IEEE-754 INVALID exceptions into Python exceptions. Other operations that produce a NaN and issue an IEEE-754 INVALID signal do not raise a Python exception. But that's not the difference between signalling NaNs and quiet NaNs. A signalling NaN is one that when it is used as an *input* to an operation, it issues an INVALID signal, not whether a signal is issued when it is the *output* of an operation. -- Robert Kern I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth. -- Umberto Eco ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Fri, Apr 29, 2011 at 11:31 AM, Robert Kern robert.k...@gmail.com wrote: .. And in fact, 0.0/0.0 is covered by the more general rule that x/0.0 raises ZeroDivisionError, not a rule that converts IEEE-754 INVALID exceptions into Python exceptions. It is unfortunate that official text of IEEE-754 is not freely available and as a result a lot of discussion in this thread is based on imperfect information. I find Kahan's Lecture Notes on the Status of IEEE Standard 754 for Binary Floating-Point Arithmetic [1] a reasonable reference in the absence of the official text. According to Kahan's notes, INVALID operation is defined as follows: Exception: INVALID operation. Signaled by the raising of the INVALID flag whenever an operation's operands lie outside its domain, this exception's default, delivered only because any other real or infinite value would most likely cause worse confusion, is NaN , which means “ Not a Number.” IEEE 754 specifies that seven invalid arithmetic operations shall deliver a NaN unless they are trapped: real √(Negative) , 0*∞ , 0.0/0.0 , ∞/∞, REMAINDER(Anything, 0.0) , REMAINDER( ∞, Anything) , ∞ - ∞ when signs agree (but ∞ + ∞ = ∞ when signs agree). Conversion from floating-point to other formats can be INVALID too, if their limits are violated, even if no NaN can be delivered. In contrast, Kahan describes DIVIDE by ZERO exception as a misnomer perpetrated for historical reasons. A better name for this exception is 'Infinite result computed Exactly from Finite operands.' Other operations that produce a NaN and issue an IEEE-754 INVALID signal do not raise a Python exception. Some do: math.sqrt(-1) Traceback (most recent call last): File stdin, line 1, in module ValueError: math domain error I think the only exception are the operations involving infinity. The likely rationale is that since infinity is not produced by python arithmetics, those who use inf are likely to expect inf*0 etc. to produce nan. The following seems to be an oversight: 1e300 * 1e300 inf compared to 1e300 ** 2 Traceback (most recent call last): File stdin, line 1, in module OverflowError: (34, 'Result too large') [1] http://www.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On Fri, Apr 29, 2011 at 12:10 AM, Stephen J. Turnbull step...@xemacs.org wrote: Other aspects of NaN behavior may be a mistake. But it's not clear to me, even after all the discussion in this thread. ISTM that the current behavior of NaN (never mind the identity issue) helps numeric experts write better code. For naive users, however, it causes puzzlement if they ever run into it. Decimal, for that reason, has a context that lets one specify different behaviors when a NaN is produced. Would it make sense to add a float context that also lets one specify what should happen? That could include returning Inf for 1.0/0.0 (for experts), or raising exceptions when NaNs are produced (for the numerically naive like myself). I could see a downside too, e.g. the correctness of code that passingly uses floats might be affected by the context settings. There's also the question of whether the float context should affect int operations; floats vs. ints is another can of worms since (in Python 3) we attempt to tie them together through 1/2 == 0.5, but ints have a much larger range than floats. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On Fri, Apr 29, 2011 at 1:11 PM, Guido van Rossum gu...@python.org wrote: … Would it make sense to add a float context that also lets one specify what should happen? That could include returning Inf for 1.0/0.0 (for experts), or raising exceptions when NaNs are produced (for the numerically naive like myself). ISTM, this is approaching py4k territory. Adding contexts will not solve backward compatibility problem unless you introduce a quirks contexts that would preserve current warts and make it default. For what it's worth, I think the next major version of Python should use decimal as its main floating point type an leave binary floats to numerical experts. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Fri, Apr 29, 2011 at 11:35, Alexander Belopolsky alexander.belopol...@gmail.com wrote: On Fri, Apr 29, 2011 at 11:31 AM, Robert Kern robert.k...@gmail.com wrote: .. And in fact, 0.0/0.0 is covered by the more general rule that x/0.0 raises ZeroDivisionError, not a rule that converts IEEE-754 INVALID exceptions into Python exceptions. It is unfortunate that official text of IEEE-754 is not freely available and as a result a lot of discussion in this thread is based on imperfect information. I find Kahan's Lecture Notes on the Status of IEEE Standard 754 for Binary Floating-Point Arithmetic [1] a reasonable reference in the absence of the official text. According to Kahan's notes, INVALID operation is defined as follows: Exception: INVALID operation. Signaled by the raising of the INVALID flag whenever an operation's operands lie outside its domain, this exception's default, delivered only because any other real or infinite value would most likely cause worse confusion, is NaN , which means “ Not a Number.” IEEE 754 specifies that seven invalid arithmetic operations shall deliver a NaN unless they are trapped: real √(Negative) , 0*∞ , 0.0/0.0 , ∞/∞, REMAINDER(Anything, 0.0) , REMAINDER( ∞, Anything) , ∞ - ∞ when signs agree (but ∞ + ∞ = ∞ when signs agree). Conversion from floating-point to other formats can be INVALID too, if their limits are violated, even if no NaN can be delivered. In contrast, Kahan describes DIVIDE by ZERO exception as a misnomer perpetrated for historical reasons. A better name for this exception is 'Infinite result computed Exactly from Finite operands.' Nonetheless, the reason that *Python* raises a ZeroDivisionError is because it checks that the divisor is 0.0, not because 0.0/0.0 would issue an INVALID signal. I didn't mean that 0.0/0.0 is a Division by Zero error as defined in IEEE-754. This is another area where Python ignores the INVALID signal and does its own thing. Other operations that produce a NaN and issue an IEEE-754 INVALID signal do not raise a Python exception. Some do: math.sqrt(-1) Traceback (most recent call last): File stdin, line 1, in module ValueError: math domain error Right. Elsewhere I gave a more exhaustive list including this one. The other is int(nan), though that becomes a Python exception for a more fundamental reason (there is no integer value that can represent it) than that the IEEE-754 standard specifies that the operation should signal INVALID. Arithmetic operations on signalling NaNs don't raise an exception either. These are the minority *exceptions* to the majority of cases where operations on Python floats that would issue an INVALID signal do not raise Python exceptions. If you want to lump all of the inf-related cases together, that's fine, but arithmetic operations on signalling NaNs and comparisons with NaNs form two more groups of INVALID operations that do not raise Python exceptions. -- Robert Kern I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth. -- Umberto Eco ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Steven D'Aprano wrote: If I do x = 0.0/0 I get an exception instead of a NAN. But the exception you get is ZeroDivisionError, so I think Python is catching this before you get to the stage of producing a NaN. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Mark Shannon wrote: NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Perhaps, but that wouldn't solve anything on its own. If this new class compares reflexively, then it still violates IEE754. Conversely, existing NaNs could be made to compare reflexively without making them a new class. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On Thu, Apr 28, 2011 at 7:17 PM, Greg Ewing greg.ew...@canterbury.ac.nz wrote: Mark Shannon wrote: NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Perhaps, but that wouldn't solve anything on its own. If this new class compares reflexively, then it still violates IEE754. Conversely, existing NaNs could be made to compare reflexively without making them a new class. And 3rd party NaNs can still do whatever the heck they want :) Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Mark Shannon wrote: Related to the discussion on Not a Number can I point out a few things that have not be explicitly addressed so far. The IEEE standard is about hardware and bit patterns, rather than types and values so may not be entirely appropriate for high-level language like Python. I would argue that the implementation of NANs is irrelevant. If NANs are useful in hardware floats -- and I think they are -- then they're just as equally useful as objects, or as strings in languages like REXX or Hypertalk where all data is stored as strings, or as quantum wave functions in some future quantum computer. NaN is *not* a number (the clue is in the name). Python treats it as if it were a number: import numbers isinstance(nan, numbers.Number) True Can be read as 'Not a Number' is a Number ;) I see your wink, but what do you make of these? class NotAnObject(object): pass nao = NotAnObject() assert isinstance(nao, object) class NotAType(object): pass assert type(NotAType) is type NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Others have already pointed out this won't make any difference. Fundamentally, the problem is that some containers bypass equality tests for identity tests. There may be good reasons for that shortcut, but it leads to problems with *any* object that does not define equality to be reflexive, not just NANs. class Null: ... def __eq__(self, other): ... return False ... null = Null() null == null False [null] == [null] True The default comparisons will then work as expected for collections. (No doubt, making NaN a new class will cause a whole new set of problems) As pointed out by Meyer: NaN == NaN is False is no more logical than NaN != NaN is False I don't agree with this argument. I think Meyer is completely mistaken there. The question of NAN equality is that of a vacuous truth, quite similar to the Present King of France: http://en.wikipedia.org/wiki/Present_King_of_France Meyer would have us accept that: The present King of France is a talking horse and The present King of France is not a talking horse are equally (pun not intended) valid. No, no they're not. I don't know much about who the King of France would be if France had a king, but I do know that he wouldn't be a talking horse. Once you accept that NANs aren't equal to anything else, it becomes a matter of *practicality beats purity* to accept that they can't be equal to themselves either. A NAN doesn't represent a specific thing. It's a signal that your calculation has generated an indefinite, undefined, undetermined value. NANs aren't equal to anything. The fact that a NAN happens to have an existence as a bit-pattern at some location, or as a distinct object, is an implementation detail that is irrelevant. If you just happen by some fluke to compare a NAN to itself, that shouldn't change the result of the comparison: The present King of France is the current male sovereign who rules France is still false, even if you happen to write it like this: The present King of France is the present King of France This might seem surprising to those who are used to reflexivity. Oh well. Just because reflexivity holds for actual things, doesn't mean it holds for, er, things that aren't things. NANs are things that aren't things. Although both NaN == NaN and NaN != NaN could arguably be a maybe value, the all important reflexivity (x == x is True) is effectively part of the language. All collections rely on it and Python wouldn't be much use without dicts, tuples and lists. Perhaps they shouldn't rely on it. Identity tests are an implementation detail. But in any case, reflexivity is *not* a guarantee of Python. With rich comparisons, you can define __eq__ to do anything you like. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Steven D'Aprano wrote: Mark Shannon wrote: Related to the discussion on Not a Number can I point out a few things that have not be explicitly addressed so far. The IEEE standard is about hardware and bit patterns, rather than types and values so may not be entirely appropriate for high-level language like Python. I would argue that the implementation of NANs is irrelevant. If NANs are useful in hardware floats -- and I think they are -- then they're just as equally useful as objects, or as strings in languages like REXX or Hypertalk where all data is stored as strings, or as quantum wave functions in some future quantum computer. So, Indeed, so its OK if type(NaN) != type(0.0) ? NaN is *not* a number (the clue is in the name). Python treats it as if it were a number: import numbers isinstance(nan, numbers.Number) True Can be read as 'Not a Number' is a Number ;) I see your wink, but what do you make of these? class NotAnObject(object): pass nao = NotAnObject() assert isinstance(nao, object) Trying to make something not an object in a language where everything is an object is bound to be problematic. class NotAType(object): pass assert type(NotAType) is type NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Others have already pointed out this won't make any difference. Fundamentally, the problem is that some containers bypass equality tests for identity tests. There may be good reasons for that shortcut, but it leads to problems with *any* object that does not define equality to be reflexive, not just NANs. class Null: ... def __eq__(self, other): ... return False ... null = Null() null == null False [null] == [null] True Just because you can do that, doesn't mean you should. Equality should be reflexive, without that fundamental assumption many non-numeric algorithms fall apart. The default comparisons will then work as expected for collections. (No doubt, making NaN a new class will cause a whole new set of problems) As pointed out by Meyer: NaN == NaN is False is no more logical than NaN != NaN is False I don't agree with this argument. I think Meyer is completely mistaken there. The question of NAN equality is that of a vacuous truth, quite similar to the Present King of France: http://en.wikipedia.org/wiki/Present_King_of_France Meyer would have us accept that: The present King of France is a talking horse and The present King of France is not a talking horse are equally (pun not intended) valid. No, no they're not. I don't know much about who the King of France would be if France had a king, but I do know that he wouldn't be a talking horse. Once you accept that NANs aren't equal to anything else, it becomes a matter of *practicality beats purity* to accept that they can't be equal Not breaking a whole bunch of collections and algorithms has a certain practical appeal as well ;) to themselves either. A NAN doesn't represent a specific thing. It's a signal that your calculation has generated an indefinite, undefined, undetermined value. NANs aren't equal to anything. The fact that a NAN happens to have an existence as a bit-pattern at some location, or as a distinct object, is an implementation detail that is irrelevant. If you just happen by some fluke to compare a NAN to itself, that shouldn't change the result of the comparison: The present King of France is the current male sovereign who rules France is still false, even if you happen to write it like this: The present King of France is the present King of France The problem with this argument is the present King of France does not exist, whereas NaN (as a Python object) does exist. The present King of France argument only applies to non-existent things. Python objects do exist (as much as any computer language entity exists). So the expression The present King of France either raises an exception (non-existence) or evaluates to an object (existence). In this case the present King of France doesn't exist and should raise a FifthRepublicException :) inf / inf does not raise an exception, but evaluates to NaN, so NaN exists. For objects (that exist): (x is x) is True. The present President of France is the present President of France, regardless of who he or she may be. This might seem surprising to those who are used to reflexivity. Oh well. Just because reflexivity holds for actual things, doesn't mean it holds for, er, things that aren't things. NANs are things that aren't things. A NaN is thing that *is* a thing; it exists: object.__repr__(float('nan')) Of course if inf - inf, inf/inf raised exceptions, then NaN wouldn't exist (as a Python object) and the problem would just go away :) After all 0.0/0.0 already raises an exception, but the IEEE defines 0.0/0.0 as NaN. Although both NaN == NaN and NaN != NaN could arguably be a maybe
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On 28/04/2011 15:58, Steven D'Aprano wrote: Fundamentally, the problem is that some containers bypass equality tests for identity tests. There may be good reasons for that shortcut, but it leads to problems with *any* object that does not define equality to be reflexive, not just NANs. I say you have that backwards. It is a legitimate shortcut, and any object that (perversely) doesn't define equality to be reflexive leads (unsurprisingly) to problems with it (and with *anything else* that - very reasonably - assumes that identity implies equality). Mark Shannon wrote: Although both NaN == NaN and NaN != NaN could arguably be a maybe value, the all important reflexivity (x == x is True) is effectively part of the language. All collections rely on it and Python wouldn't be much use without dicts, tuples and lists. Perhaps they shouldn't rely on it. Identity tests are an implementation detail. But in any case, reflexivity is *not* a guarantee of Python. With rich comparisons, you can define __eq__ to do anything you like. And you can write True = False (at least in older versions of Python you could). No language stops you from writing stupid programs. In fact I would propose that the language should DEFINE the meaning of == to be True if its operands are identical, and only if they are not would it use the comparison operators, thus enforcing reflexivity. (Nothing stops you from writing your own non-reflexive __eq__ and calling it explicitly, and I think it is right that you should have to work harder and be more explicit if you want that behaviour.) Please, please, can we have a bit of common sense and perspective here. No-one (not even a mathematician) except someone from Wonderland would seriously want an object not equal to itself. Regards Rob Cliffe ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Mark Shannon wrote: Steven D'Aprano wrote: Mark Shannon wrote: Related to the discussion on Not a Number can I point out a few things that have not be explicitly addressed so far. The IEEE standard is about hardware and bit patterns, rather than types and values so may not be entirely appropriate for high-level language like Python. I would argue that the implementation of NANs is irrelevant. If NANs are useful in hardware floats -- and I think they are -- then they're just as equally useful as objects, or as strings in languages like REXX or Hypertalk where all data is stored as strings, or as quantum wave functions in some future quantum computer. So, Indeed, so its OK if type(NaN) != type(0.0) ? Sure. But that just adds complexity without actually resolving anything. Fundamentally, the problem is that some containers bypass equality tests for identity tests. There may be good reasons for that shortcut, but it leads to problems with *any* object that does not define equality to be reflexive, not just NANs. [...] Just because you can do that, doesn't mean you should. Equality should be reflexive, without that fundamental assumption many non-numeric algorithms fall apart. So what? If I have a need for non-reflexivity in my application, why should I care that some other algorithm, which I'm not using, will fail? Python supports non-reflexivity. If I take advantage of that feature, I can't guarantee that *other objects* will be smart enough to understand this. This is no different from any other property of my objects. The default comparisons will then work as expected for collections. (No doubt, making NaN a new class will cause a whole new set of problems) As pointed out by Meyer: NaN == NaN is False is no more logical than NaN != NaN is False I don't agree with this argument. I think Meyer is completely mistaken there. The question of NAN equality is that of a vacuous truth, quite similar to the Present King of France: http://en.wikipedia.org/wiki/Present_King_of_France [...] The problem with this argument is the present King of France does not exist, whereas NaN (as a Python object) does exist. NANs (as Python objects) exist in the same way as the present King of France exists as words. It's an implementation detail: we can't talk about the non-existent present King of France without using words, and we can't do calculations on non-existent/indeterminate values in Python without objects. Words can represent things that don't exist, and so can bit-patterns or objects or any other symbol. We must be careful to avoid mistaking the symbol (the NAN bit-pattern or object) for the thing (the result of whatever calculation generated that NAN). The idea of equality we care about is equality of what the symbol represents, not the symbol itself. The meaning of spam and eggs should not differ according to the typeface we write the words in. Likewise the number 42 should not differ according to how the int object is laid out, or whether the bit-pattern is little-endian or big-endian. What matters is the thing itself, 42, not the symbol: it will still be 42 even if we decided to write it in Roman numerals or base 13. Likewise, what matters is the non-thingness of NANs, not the fact that the symbol for them has an existence as an object or a bit-pattern. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
On 4/28/2011 4:40 AM, Mark Shannon wrote: NaN is *not* a number (the clue is in the name). The problem is that the committee itself did not believe or stay consistent with that. In the text of the draft, they apparently refer to Nan as an indefinite, unspecified *number*. Sort of like a random variable with a uniform pseudo* distribution over the reals (* 0 everywhere with integral 1). Or a quantum particle present but smeared out over all space. And that apparently is their rationale for Nan != NaN: an unspecified number will equal another unspecified number with probability 0. The rationale for bool(NaN)==True is that an unspecified *number* will be 0 with probability 0. If Nan truly indicated an *absence* (like 0 and '') then bool(NaN) should be False, I think the committee goofed -- badly. Statisticians used missing value indicators long before the committee existed. They has no problem thinking that the indicator, as an object, equaled itself. So one could write (and I often did through the 1980s) the equivalent of for i,x in enumerate(datavec): if x == XMIS: # singleton missing value indicator for BMDP datavec[i] = default (Statistics packages have no concept of identity different from equality.) If statisticians had made XMIS != XMIS, that obvious code would not have worked, as it will not today for Python. Instead, the special case circumlocution of if isXMIS(x): would have been required, adding one more unnecessary function to the list of builtins. NaN is, in its domain, the equivalent of None (== Not a Value), which also serves an an alternative to immediately raising an exception. But like XMIS, None==None. Also, bool(None) is corretly for something that indicates absence. Python treats it as if it were a number: As I said, so did the committee, and that was its mistake that we are more or less stuck with. NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Like None As pointed out by Meyer: NaN == NaN is False is no more logical than NaN != NaN is False This is wrong if False/True are interpreted as probabilities 0 and 1. To summarise: NaN is required so that floating point operations on arrays and lists do not raise unwanted exceptions. Like None. NaN is Not a Number (therefore should be neither a float nor a Decimal). Making it a new class would solve some of the problems discussed, but would create new problems instead. Agreed, if we were starting fresh. Correct behaviour of collections is more important than IEEE conformance of NaN comparisons. Also agreed. -- Terry Jan Reedy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number (was PyObject_RichCompareBool identity shortcut)
Terry Reedy wrote: I think the committee goofed -- badly. Statisticians used missing value indicators long before the committee existed. They has no problem thinking that the indicator, as an object, equaled itself. So one could write (and I often did through the 1980s) the equivalent of for i,x in enumerate(datavec): if x == XMIS: # singleton missing value indicator for BMDP datavec[i] = default But NANs aren't missing values (although some people use them as such, that can be considered abuse of the concept). R distinguishes NANs from missing values: they have a built-in value NaN, and a separate built-in value NA which is the canonical missing value. R also treats comparisons of both special values as a missing value: NA == NA [1] NA NaN == NaN [1] NA including reflexivity: x = NA x == x [1] NA which strikes me as the worst of both worlds, guaranteed to annoy those who want the IEEE behaviour where NANs compare unequal, those like Terry who expect missing values to compare equal to other missing values, and those who want reflexivity to be treated as an invariant no matter what. NaN is Not a Number (therefore should be neither a float nor a Decimal). Making it a new class would solve some of the problems discussed, but would create new problems instead. Agreed, if we were starting fresh. I don't see that making NANs a separate class would make any practical difference what-so-ever, but the point is moot since we're not starting fresh :) Correct behaviour of collections is more important than IEEE conformance of NaN comparisons. Also agreed. To be pedantic, the IEEE standard doesn't have anything to say about comparisons of lists of floats that might contain NANs. Given the current *documented* behaviour that list equality is based on object equality, the actual behaviour is surprising, but I don't think there is anything wrong with the idea of containers assuming that their elements are reflexive. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Terry Reedy tjre...@udel.edu writes: On 4/28/2011 4:40 AM, Mark Shannon wrote: NaN does not have to be a float or a Decimal. Perhaps it should have its own class. Like None Would it make sense for ‘NaN’ to be another instance of ‘NoneType’? -- \ “I am too firm in my consciousness of the marvelous to be ever | `\ fascinated by the mere supernatural …” —Joseph Conrad, _The | _o__) Shadow-Line_ | Ben Finney ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? +Inf and -Inf are arguably useful elements of the algebra, yet Python insists on raising an exception for 1.0./0.0 instead of returning an infinity. Why do this but not raise an exception for any operation that produces a NaN? -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On Fri, Apr 29, 2011 at 11:11 AM, Ben Finney ben+pyt...@benfinney.id.au wrote: Would it make sense for ‘NaN’ to be another instance of ‘NoneType’? This is fine IHMO as I (personally) find myself doing things like: if x is None: ... cheers James -- -- James Mills -- -- Problems are solved by method ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Greg Ewing wrote: Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? The real question should be, why does Python treat all NANs as signalling NANs instead of quiet NANs? I don't believe this helps anyone. +Inf and -Inf are arguably useful elements of the algebra, yet Python insists on raising an exception for 1.0./0.0 instead of returning an infinity. I would argue that Python is wrong to do so. As I've mentioned a couple of times now, 20 years ago Apple felt that NANs and INFs weren't too complicated for non-programmers using Hypercard. There's no sign that Apple were wrong to expose NANs and INFs to users, no flood of Hypercard users confused by NAN inequality. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
On 4/28/11 8:44 PM, Steven D'Aprano wrote: Greg Ewing wrote: Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? The real question should be, why does Python treat all NANs as signalling NANs instead of quiet NANs? I don't believe this helps anyone. Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. -- Robert Kern I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth. -- Umberto Eco ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Not-a-Number
Robert Kern wrote: On 4/28/11 8:44 PM, Steven D'Aprano wrote: Greg Ewing wrote: Taking a step back from all this, why does Python allow NaNs to arise from computations *at all*? The real question should be, why does Python treat all NANs as signalling NANs instead of quiet NANs? I don't believe this helps anyone. Actually, Python treats all NaNs as quiet NaNs and never signalling NaNs. Sorry, did I get that backwards? I thought it was signalling NANs that cause a signal (in Python terms, an exception)? If I do x = 0.0/0 I get an exception instead of a NAN. Hence a signalling NAN. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Summaries for Number 2008, First Half
Thanks for getting back to this! On Sun, Nov 16, 2008, Calvin Spealman wrote: --- Optionally using GMP to implement long if available --- I'd combine the long optimization thread here -- I don't see any reason for separate thread summaries. Or at least put them next to each other. --- hg branch gone? --- I'd skip this thread -- My patches -- The summary should use clear titles, especially if they don't have an actual summary for a thread. I'd title this How do I get my patches accepted? or Can someone please look at my patches? -- Aahz ([EMAIL PROTECTED]) * http://www.pythoncraft.com/ It is easier to optimize correct code than to correct optimized code. --Bill Harlan ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com