Why does NaN^0 == 1

RMathNaArithmetic Expressions

R Problem Overview


Prompted by a spot of earlier code golfing why would:

>NaN^0
[1] 1

It makes perfect sense for NA^0 to be 1 because NA is missing data, and any number raised to 0 will give 1, including -Inf and Inf. However NaN is supposed to represent not-a-number, so why would this be so? This is even more confusing/worrying when the help page for ?NaN states:

> In R, basically all mathematical functions (including basic > Arithmetic), are supposed to work properly with +/- Inf and NaN as > input or output. > > The basic rule should be that calls and relations with Infs really are > statements with a proper mathematical limit. > > Computations involving NaN will return NaN or perhaps NA: which of > those two is not guaranteed and may depend on the R platform (since > compilers may re-order computations).

Is there a philosophical reason behind this, or is it just to do with how R represents these constants?

R Solutions


Solution 1 - R

This is referenced in the help page referenced by ?'NaN'

"The IEC 60559 standard, also known as the ANSI/IEEE 754 Floating-Point Standard.

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

And there you find this statement regarding what should create a NaN:

 "There are three kinds of operations that can return NaN:[5]
       Operations with a NaN as at least one operand.

It is probably is from the particular C compiler, as signified by the Note you referenced. This is what the GNU C documentation says:

http://www.gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html

" NaN, on the other hand, infects any calculation that involves it. Unless the calculation would produce the same result no matter what real value replaced NaN, the result is NaN."

So it seems that the GNU-C people have a different standard in mind when writing their code. And the 2008 version of ANSI/IEEE 754 Floating-Point Standard is reported to make that suggestion:

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

The published standard is not free. So if you are have access rights or money you can look here:

http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=4610933

Solution 2 - R

The answer can be summed up by "for historical reasons".

It seems that IEEE 754 introduced two different power functions - pow and powr, with the latter preserving NaN's in the OP case and also returning NaN for Inf^0, 0^0, 1^Inf, but eventually the latter was dropped as explained briefly here.

Conceptually, I'm in the NaN preserving camp, because I'm coming at the issue from viewpoint of limits, but from convenience point of view I expect current conventions are slightly easier to deal with, even if they don't make a lot of sense in some cases (e.g. sqrt(-1)^0 being equal to 1 while all operations are on real numbers makes little sense if any).

Solution 3 - R

Yes, I'm late here, but as R Core member who was involved in this design, let me recall what I commented above. NaN preserving and NA preserving work "equivalently" in R, so if you agree that NA^0 should give 1, NaN^0 |-> 1 is a consequence.

Indeed (as others said) you should really read R's help pages and not C or IEEE standards, to answer such questions, and SimonO101 correctly cited

> 1 ^ y and y ^ 0 are 1, always

and I'm pretty sure that I was heavily involved (if not the author) of that. Note that it is good, not bad, to be able to provide non-NaN answers, also in cases other programming languages do differently. The consequence of such a rule is that more things work automatically correctly; in the other case, the R programmer would have been urged to do more special casing herself.

Or put differently, a simple rule as the above (returning non-NaN in all cases) is a good rule, because it propagates continuity in a mathematical sense: lim_x f(x) = f(lim x). We have had a few cases where it was clearly adavantageous (i.e. did not need special casing, I'm repeating..) to adhere to the above "= 1" rule, rather than to propagate NaN. As I said further up, the sqrt(-1)^0 is also such an example, as 1 is the correct result as soon as you extend to the complex plane.

Solution 4 - R

Here's one reasoning. From Goldberg:

> In IEEE 754, NaNs are often represented as floating-point numbers with > the exponent e_max + 1 and nonzero significands.

So NaN is a floating-point number, though with a special meaning. Raising a number to the power zero sets its exponent to zero, therefore it will no longer be NaN.

Also note:

> 1^NaN
[1] 1

One is a number whose exponent is zero already.

Solution 5 - R

Conceptually, the only problem with NaN^0 == 1 is that zero values can come about at least four different ways, but the IEEE format uses the same representation for three of them. The above formula equality sense for the most common case (which is one of the three), but not for the others.

BTW, the four cases I would recognize would be:

  • A literal zero
  • Unsigned zero: the difference between two numbers that are indistinguishable
  • Positive infinitesimal: The product or quotient of two numbers of matching sign, which is too small to be distinguished from zero.
  • Negative infinitesimal: The product or quotient of two numbers of opposite sign, which is too small to be distinguished from zero.

Some of these may be produced via other means (e.g. literal zero could be produced as the sum of two literal zeros; positive infinitesimal by the division of a very small number by a very large one, etc.).

If a floating-point recognized the above, it could usefully regard raising NaN to a literal zero as yielding one, and raising it to any other kind of zero as yielding NaN; such a rule would allow a constant result to be assumed in many cases where something that might be NaN would be raised to something the compiler could identify as a constant zero, without such assumption altering program semantics. Otherwise, I think the issue is that most code isn't going to care whether x^0 might would NaN if x is NaN, and there's not much point to having a compiler add code for conditions code isn't going to care about. Note that the issue isn't just the code to compute x^0, but for any computations based on that which would be constant if x^0 was.

Solution 6 - R

If you look at the type of NaN, it is still a number, it's just not a specific number that can be represented by the numeric type.

EDIT:

For example, if you were to take 0/0. What is the result? If you tried to solve this equation on paper, you get stuck at the very first digit, how many zero's fit into another 0? You can put 0, you can put 1, you can put 8, they all fit into 0*x=0 but it's impossible to know which one the correct answer is. However, that does not mean the answer is no longer a number, it's just not a number that can be represented.

Regardless, any number, even a number that you can't represent, to the power of zero is still 1. If you break down some math x^8 * x^0 can be further simplified by x^(8+0) which equates to x^8, where did the x^0 go? It makes sense if x^0 = 1 because then the equation x^8 * 1 explains why x^0 just sort of disappears from existence.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSimon O'HanlonView Question on Stackoverflow
Solution 1 - RIRTFMView Answer on Stackoverflow
Solution 2 - ReddiView Answer on Stackoverflow
Solution 3 - RMartin MächlerView Answer on Stackoverflow
Solution 4 - RJamesView Answer on Stackoverflow
Solution 5 - RsupercatView Answer on Stackoverflow
Solution 6 - RLochemageView Answer on Stackoverflow