Pourquoi NaN ^ 0 == 1

Invité par un spot de golf antérieur, pourquoi:

>NaN^0 [1] 1 

Il est tout à fait logique que NA^0 soit égal à 1 car NA ne contient pas de données, et tout nombre élevé à 0 donnera 1, y compris -Inf et Inf . Cependant, NaN est censé représenter non-un-numéro , alors pourquoi serait-ce ainsi? Ceci est encore plus déroutant / inquiétant lorsque la page d’aide de ?NaN indique:

Dans R, toutes les fonctions mathématiques (y compris l’arithmétique de base) sont supposées fonctionner correctement avec +/- Inf et NaN comme entrées ou sorties.

La règle de base devrait être que les appels et les relations avec Infs sont vraiment des déclarations avec une limite mathématique correcte.

Les calculs impliquant NaN renverront NaN ou peut-être NA : lequel de ces deux n’est pas garanti et peut dépendre de la plate-forme R (puisque les compilateurs peuvent réorganiser les calculs).

Y a-t-il une raison philosophique derrière cela, ou est-ce juste lié à la manière dont R représente ces constantes?

Ceci est référencé dans la page d’aide référencée par ?'NaN'

“La norme IEC 60559, également connue sous le nom de norme à virgule flottante ANSI / IEEE 754.

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

Et là vous trouvez cette déclaration concernant ce qui devrait créer un NaN:

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

C’est probablement du compilateur C particulier, comme indiqué par la note que vous avez référencée. Voici ce que dit la documentation GNU:

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

“En revanche, NaN infecte tout calcul qui l’implique. À moins que le calcul produise le même résultat, quelle que soit la valeur réelle remplacée par NaN, le résultat est NaN.”

Il semble donc que les gens de GNU-C ont une norme différente en tête lors de la rédaction de leur code. Et la version 2008 de la norme à virgule flottante ANSI / IEEE 754 serait utilisée pour faire cette suggestion:

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

La norme publiée n’est pas gratuite. Donc, si vous avez des droits d’access ou de l’argent, vous pouvez regarder ici:

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

La réponse peut être résumée par “pour des raisons historiques”.

Il semble que IEEE 754 ait introduit deux fonctions de puissance différentes – pow et powr , cette dernière préservant les NaN dans le cas OP et renvoyant également NaN pour Inf^0 , 0^0 , 1^Inf , mais finalement cette dernière a été supprimée comme expliqué brièvement ici .

D’un sharepoint vue conceptuel, je suis dans le camp de préservation de NaN , car j’aborde la question du sharepoint vue des limites, mais du sharepoint vue de la commodité, je m’attends à ce que les conventions actuelles soient un peu plus faciles à gérer. de sens dans certains cas (par exemple sqrt(-1)^0 étant égal à 1 alors que toutes les opérations sont sur des nombres réels a peu de sens, le cas échéant).

Oui, je suis en retard ici, mais en tant que membre de R Core impliqué dans cette conception, laissez-moi vous rappeler ce que j’ai commenté ci-dessus. NaN conservant et NA conservant un travail “de manière équivalente” dans R, donc si vous êtes d’accord que NA ^ 0 devrait donner 1, NaN ^ 0 | -> 1 est une conséquence.

En effet (comme d’autres l’ont dit), vous devriez vraiment lire les pages d’aide de R et non les normes C ou IEEE, pour répondre à ces questions, et SimonO101 a correctement cité

1 ^ y et y ^ 0 sont 1, toujours

et je suis à peu près sûr que j’étais très impliqué (sinon l’auteur) de cela. Notez que c’est bien , pas mal, de pouvoir fournir des réponses non-NaN, même dans les cas où d’autres langages de programmation fonctionnent différemment. La conséquence d’une telle règle est que plus de choses fonctionnent automatiquement correctement; dans l’autre cas, le programmeur R aurait été invité à faire plus de casse spéciale elle-même.

Ou en d’autres termes, une règle simple comme ci-dessus (renvoyant dans tous les cas non-NaN) est une bonne règle, car elle propage la continuité au sens mathématique: lim_x f (x) = f (lim x). Nous avons eu quelques cas où il était clairement avantageux (c.-à-d. Ne nécessitant pas de boîtiers spéciaux, je répète ..) pour adhérer à la règle “= 1” ci-dessus, plutôt que de propager NaN. Comme je l’ai dit plus haut, le sqrt (-1) ^ 0 est aussi un exemple, car 1 est le résultat correct dès que vous vous étendez dans le plan complexe.

Voici un raisonnement. De Goldberg :

Dans IEEE 754, les NaN sont souvent représentés par des nombres à virgule flottante avec les exposants e_max + 1 et les non-significatives.

Donc, NaN est un nombre à virgule flottante, mais avec une signification particulière. Augmenter un nombre à zéro remet son exposant à zéro, il ne sera donc plus NaN.

Notez également:

 > 1^NaN [1] 1 

L’un est un nombre dont l’exposant est déjà zéro.

D’un sharepoint vue conceptuel, le seul problème avec NaN^0 == 1 est que les valeurs nulles peuvent avoir au moins quatre manières différentes, mais le format IEEE utilise la même représentation pour trois d’entre elles. Le sens d’égalité de la formule ci-dessus pour le cas le plus courant (qui est l’un des trois), mais pas pour les autres.

BTW, les quatre cas que je reconnaîtrais seraient:

  • Un zéro littéral
  • Zéro non signé: la différence entre deux nombres indiscernables
  • Positif infinitésimal: Produit ou quotient de deux nombres de signes correspondants, trop petit pour être distingué de zéro.
  • Infinitésimal négatif: Le produit ou le quotient de deux nombres de signe opposé, trop petit pour être distingué de zéro.

Certains d’entre eux peuvent être produits par d’autres moyens (par exemple, le zéro littéral pourrait être la sum de deux zéros littéraux; l’infinitésimal positif par la division d’un très petit nombre par un très grand nombre, etc.).

Si un nombre à virgule flottante reconnaissait ce qui précède, on pourrait utilement considérer que le fait d’élever NaN à un zéro littéral en génère un, et de le porter à un autre type de zéro pour obtenir NaN; une telle règle permettrait de supposer un résultat constant dans de nombreux cas où quelque chose qui pourrait être NaN serait porté à quelque chose que le compilateur pourrait identifier comme un zéro constant, sans que cette hypothèse modifie la sémantique du programme. Sinon, je pense que le problème est que la plupart du code ne va pas se soucier de savoir si x^0 pourrait NaN si x est NaN , et il n’ya pas grand chose à avoir un code d’ajout de compilateur pour les conditions dont le code ne compte pas. Notez que le problème n’est pas simplement le code pour calculer x^0 , mais pour tous les calculs basés sur ce qui serait constant si x^0 était.

Si vous regardez le type de NaN, il s’agit toujours d’un nombre, mais ce n’est pas un nombre spécifique pouvant être représenté par le type numérique.

MODIFIER:

Par exemple, si vous deviez prendre 0/0. Quel est le résultat? Si vous avez essayé de résoudre cette équation sur papier, vous êtes bloqué au tout premier chiffre, combien de zéro correspondent à un autre 0? Vous pouvez mettre 0, vous pouvez mettre 1, vous pouvez mettre 8, ils entrent tous dans 0 * x = 0 mais il est impossible de savoir lequel est la bonne réponse. Cependant, cela ne signifie pas que la réponse n’est plus un chiffre, mais qu’elle ne peut être représentée.

Peu importe, n’importe quel nombre, même un nombre que vous ne pouvez pas représenter, à la puissance de zéro est toujours 1. Si vous décomposez des calculs, x^8 * x^0 peut être encore simplifié par x^(8+0) équivaut à x^8 , où est passé le x^0 ? Cela a du sens si x^0 = 1 car alors l’équation x^8 * 1 explique pourquoi x^0 disparaît en quelque sorte de l’existence.