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


Groups > comp.lang.python > #7066

Re: float("nan") in set or as key

From Chris Torek <nospam@torek.net>
Newsgroups comp.lang.python
Subject Re: float("nan") in set or as key
Date 2011-06-06 01:56 +0000
Organization None of the Above
Message-ID <ishc5302ne4@news7.newsguy.com> (permalink)
References <4de6df06$0$29996$c3e8da3$5496439d@news.astraweb.com> <ish1fg029vl@news1.newsguy.com> <mailman.2475.1307315609.9059.python-list@python.org> <4dec2ba6$0$29996$c3e8da3$5496439d@news.astraweb.com>

Show all headers | View raw


>> On Mon, Jun 6, 2011 at 8:54 AM, Chris Torek <nospam@torek.net> wrote:
>>> A signalling NaN traps at (more or less -- details vary depending on
>>> FPU architecture) load time.

>On Mon, 06 Jun 2011 09:13:25 +1000, Chris Angelico wrote:
>> Load. By this you mean the operation of taking a bit-pattern in RAM and
>> putting it into a register? So, you can calculate 0/0, get a signalling
>> NaN, and then save that into a memory variable, all without it trapping;
>> and then it traps when you next perform an operation on that number?

I mean, if you think of the FPU as working (in principle) with
either just one or two registers and a load/store architecture, or
a tiny little FPU-stack (the latter is in fact the case for Intel
FPUs), with no optimization, you get a trap when you attempted to
load-up the sNaN value in order to do some operation on it.  For
instance, if x is an sNaN, "y = x + 1" turns into "load x; load
1.0; add; store y" and the trap occurs when you do "load x".

In article <4dec2ba6$0$29996$c3e8da3$5496439d@news.astraweb.com>,
Steven D'Aprano  <steve+comp.lang.python@pearwood.info> wrote:
>The intended behaviour is operations on "quiet NANs" should return NANs, 
>but operations on "signalling NANs" should cause a trap, which can either 
>be ignored, and converted into a quiet NAN, or treated as an exception.
>
>E.g. in Decimal:
>
>>>> import decimal
>>>> qnan = decimal.Decimal('nan')  # quiet NAN
>>>> snan = decimal.Decimal('snan')  # signalling NAN
>>>> 1 + qnan
>Decimal('NaN')
>>>> 1 + snan
>Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "/usr/local/lib/python3.1/decimal.py", line 1108, in __add__
>    ans = self._check_nans(other, context)
>  File "/usr/local/lib/python3.1/decimal.py", line 746, in _check_nans
>    self)
>  File "/usr/local/lib/python3.1/decimal.py", line 3812, in _raise_error
>    raise error(explanation)
>decimal.InvalidOperation: sNaN

Moreover:

   >>> cx = decimal.getcontext()
   >>> cx
   Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, Overflow, InvalidOperation])
   >>> cx.traps[decimal.InvalidOperation] = False
   >>> snan
   Decimal("sNaN")
   >>> 1 + snan
   Decimal("NaN")

so as you can see, by ignoring the InvalidOperation exception, we
had our sNaN converted to a (regular, non-signal-ing, "quiet") NaN,
and 1 + NaN is still NaN.

(I admit that my mental model using "loads" can mislead a bit since:

    >>> cx.traps[decimal.InvalidOperation] = True # restore trapping
    >>> also_snan = snan
    >>>

A simple copy operation is not a "load" in this particular sense,
and on most real hardware, one just uses an ordinary 64-bit integer
memory-copying operation to copy FP bit patterns from one place to
another.)

There is some good information on wikipedia:

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

(Until I read this, I was not aware that IEEE now recommends that
the quiet-vs-signal bit be 1-for-quiet 0-for-signal. I prefer the
other way around since you can then set memory to all-1-bits if it
contains floating point numbers, and get exceptions if you refer
to a value before seting it.)
-- 
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

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Re: float("nan") in set or as key Carl Banks <pavlovevidence@gmail.com> - 2011-06-03 13:27 -0700
  Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-04 06:35 +1000
    Re: float("nan") in set or as key Chris Torek <nospam@torek.net> - 2011-06-05 22:54 +0000
      Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-06 09:13 +1000
        Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-06 01:21 +0000
          Re: float("nan") in set or as key Chris Torek <nospam@torek.net> - 2011-06-06 01:56 +0000
          Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-06 14:11 +1000
            Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-06 04:59 +0000
              Re: float("nan") in set or as key Chris Angelico <rosuav@gmail.com> - 2011-06-06 15:10 +1000
  Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-04 04:54 +0000
    Re: float("nan") in set or as key Ethan Furman <ethan@stoneleaf.us> - 2011-06-03 23:04 -0700
      Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-04 09:35 +0000
        Re: float("nan") in set or as key Ben Finney <ben+python@benfinney.id.au> - 2011-06-04 20:20 +1000
        Re: float("nan") in set or as key Ethan Furman <ethan@stoneleaf.us> - 2011-06-04 14:28 -0700
        Re: float("nan") in set or as key Robert Kern <robert.kern@gmail.com> - 2011-06-04 16:49 -0500
          Re: float("nan") in set or as key Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-06-05 02:03 +0000
            Re: float("nan") in set or as key Robert Kern <robert.kern@gmail.com> - 2011-06-05 14:44 -0500

csiph-web