12

I'm surprised that

>>> import math
>>> 1**math.nan
1.0

And while we are at it, also that

>>> 0j**math.nan
0j

I didn't find any other examples. Is there a reason or some logic I've missed that makes this the right choice? Or is this a slip?

I was expecting nan. As for every other number except 1 or 0j.

Edit 1: Thanks to jedwards's comment below I have a reference. But I still don't understand why. Why was this decided as the standard? Also, couldn't find reference to 0j**mat.nan...

Edit 2: So following the answers below and some other stuff, the logic may be this one: Any calculation involving nan should return nan unless the calculation is always returning the same answer regardless of arguments. In such cases, the fact that we have nan as an argument should not affect the result and we should still get the fixed answer.

This certainly explains 1**math.nan and math.nan**0. This also explains why 0**math.nan gives nan and not 0 (since 0**n is 0 for all but when n=0 where it results with 1), and might be stretched to cover why math.nan*0 is nan if we agree that the argument need not be finite.

But if this is the logic behind the scene, then 0j**math.nan should have been nan, since 0j**n is 0 for all n's except n=0 where 0j**0 is 1. So... does 0j**math.nan have different reasoning? or is it a problem in implementation?

Aguy
  • 7,851
  • 5
  • 31
  • 58
  • There is definitely logic behind it -- an IEEE standard if I'm not mistaken. Let me try to find the relevant docs. – jedwards Jul 31 '16 at 15:57
  • Where does your surprise come from? What did you expect these expressions would evaluate to instead? – arekolek Jul 31 '16 at 16:00
  • Related: http://stackoverflow.com/questions/14414430/why-0-0-equals-1-in-python – Bakuriu Jul 31 '16 at 16:01
  • 3
    nan**0 == 1 another surprise for your list – wim Jul 31 '16 at 16:02
  • 2
    I was wrong about it being IEEE-754, it looks like it's the [C99 standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf), Annex F (`1**NaN` is specified in F.9.44, for example) – jedwards Jul 31 '16 at 16:05
  • 11
    522 pages of light bedtime reading – wim Jul 31 '16 at 16:07
  • One great thing of SO is that there is always one guy who actually RTFM. – Klaus D. Jul 31 '16 at 17:47
  • @jedwards, thanks. But I still don't understand "why?". Also couldn't find a reference to `0j`. – Aguy Jul 31 '16 at 18:27
  • Regarding the Python 3.x tags, this can be reproduced in Python 2.x using `1**float('nan')` and `0j**float('nan')` with the same behavior. – rp.beltran Jul 31 '16 at 19:22
  • @rp.beltran - Added python-2 tag. – Aguy Jul 31 '16 at 19:49
  • 2
    Related: https://bugs.python.org/issue15996 - `0j**math.nan` => `pow(0j, complex(float('nan')))` – Caramiriel Jul 31 '16 at 20:43
  • 3
    Simple answer: the Python devs have spent time getting the corner cases right for `**` on floats, but no-one has looked at the complex `pow` corner cases in detail. On a system with IEEE 754 doubles, plain old `**` for floats follows the various standards out there (IEEE 754-2008, C99 Annex F, etc.). `**` for complex has never been fixed up properly for special values and corner cases. – Mark Dickinson Aug 01 '16 at 07:47

1 Answers1

6

Quoting this question which in turns quotes IEEE 754 (see Wikipedia),

The 2008 version of the IEEE 754 standard says that pow(1,qNaN) and pow(qNaN,0) should both return 1 since they return 1 whatever else is used instead of quiet NaN.

For details see page 56 of IEEE 754 2008:

pow(x, ±0) is 1 for any x (even a zero, quiet NaN, or infinity)

pow(±0, y) is ±∞ and signals the divideByZero exception for y an odd

Thus, the reasoning seems to be that no matter what number k is in the exponent, 1^k = 1, 1^Nan should also be 1. Why that reasoning is reasonable (I'm sure it is) I'll need to dig further.

Personally, I think this makes sense - Nan doesn't really exist in math, it's just that our floating point representation can't handle it (or, Nan is "the computation is too much, this is some number but not sure which"). Thus, 1^Nan could be 1 to an arbitrary power (not 1 to something that is not a number), but since the answer will always be 1, it can only help if we define 1^Nan to be 1.

Community
  • 1
  • 1
zw324
  • 26,764
  • 16
  • 85
  • 118