On Sat, 15 Jun 2013 12:03:08 +1000, Cameron Simpson wrote: > | ... even taking that into account! *wink* | > | Everyone is aware that there is more than one NAN, right? > > I was not. Interesting. > > | If my > | calculations are correct, there are 9007199254740992 distinct float > | NANs in Python (although there is no direct way of distinguishing > | them). > > Wouldn't id() do it? At least in terms of telling them apart? I gather > they're not inspectable in Python?
I'm not talking about different *objects*. It would be terribly wasteful for Python to pre-allocate 9-gazillion NAN objects. I'm talking about distinct values, in the C-double sense. Python may or may not cache floats in general. In general, it doesn't: py> x = 2.5 py> y = 2.5 py> x is y False but in principle Python might choose to cache some, or all float objects, like it does with some ints and strings: # simulated, not real py> x = 0.0 py> y = 0.0 py> x is y True So you can always distinguish two floats, including NANs, *by value* with == and by *object identity* with id() and `is`. But that's not what I'm referring to. The layout of a C double (the numeric value of a float object) is 64 bits: |s|..e..|......f......| where s is a single sign bit, e is an 11-bit biased exponent, and f is a 52-bit binary fraction. If e is 2047 (0b11111111111) then the double is a special value, either an INF or a NAN: e = 2047, f == 0: double is +INF or -INF, depending on s e = 2047, f != 0: double is a NAN With a 52-bit f field, there are 4503599627370496 distinct payloads with the sign bit set, and another 4503599627370496 with it cleared. Python gives you no direct way of testing or setting that payload, or for that matter the sign bit, on a NAN, although you can use the struct module to cast a float to a 64-bit int and then do bit twiddling. But in principle, with 51 (why not 52? see below) bits available, you can stuff quite a fair bit of diagnostic information in a NAN, if you need to. The high bit of f is reserved for a special purpose. If the high bit is set (i.e. f >> 51 == 1) the NAN is considered a signalling NAN, which (in implementations that comply with the IEEE 754 standard) are guaranteed to halt the calculation immediately. Those with it cleared are quiet NANs, and are intended to propagate through calculations[1], although that is configurable[2]. [1] It's not quite true that once a NAN has entered a calculation, it is guaranteed to be the final result. There are circumstances where NANs can legitimately disappear from a calculation, leaving an actual number. [2] Python doesn't allow you to configure float's behaviour but the Decimal module does. -- Steven -- http://mail.python.org/mailman/listinfo/python-list