Pourquoi Math.pow (0, 0) === 1?

85

Nous savons tous que 0 0 est indéterminé.

Mais , javascript dit que:

Math.pow(0, 0) === 1 // true

et C ++ dit la même chose:

pow(0, 0) == 1 // true

POURQUOI?

Je le sais:

>Math.pow(0.001, 0.001)
0.9931160484209338

Mais pourquoi ne Math.pow(0, 0)jette aucune erreur? Ou peut-être que ce NaNserait mieux que 1.

Ionică Bizău
la source
3
@zzzzBov: Selon la définition standard, "a <sup> b </sup> = exp (b ln (a))", il n'est pas défini. Essayer de le définir comme "limite <sub> x-> 0 </sub> f (x) <sup> g (x) </sup>" où "f" et "g" ont tous deux des limites de zéro donne un indéterminé value, car cela dépend de votre choix de fonctions. (Excuses pour la notation mutilée; je ne peux pas comprendre comment obtenir des exposants dans les commentaires).
Mike Seymour
@MikeSeymour, oui, je suis conscient que 0⁰ (utiliser des caractères unicode) n'est pas défini étant donné cette définition, cependant, si vous lisez mon commentaire, vous devriez noter que la citation fait référence au "monde des mathématiques" plutôt qu'à une "définition standard". C'est à cette différence que je parlais à l'origine, et la question a été mise à jour pour corriger cette nuance.
zzzzBov
2
@AJMansfield Um ... a ^ 0 = 1 pour non nul a.
Beska
Il permet aux fonctions qui dépendent de produits de probabilités de fournir des résultats raisonnables. C'est une notion erronée que les ordinateurs sont des processeurs mathématiques symboliques. Le langage C a une implémentation spécifique dans le monde réel tandis que votre monde mathématique peut être trop idéal pour être implémenté en silicium.
IRTFM
26
Pour la version mathématique de cette question - «pourquoi définissons-nous souvent 0 ^ 0 = 1?» - math.stackexchange a beaucoup de bonnes réponses: math.stackexchange.com/questions/11150/…
PLL

Réponses:

78

En C ++ Le résultat de pow (0, 0) le résultat est fondamentalement un comportement défini par l'implémentation puisque mathématiquement nous avons une situation contradictoire où N^0devrait toujours être 1mais 0^Ndevrait toujours être 0pour N > 0, donc vous ne devriez pas non plus avoir d'attentes mathématiques quant au résultat de ceci. Ce message du forum Wolfram Alpha donne un peu plus de détails.

Bien que le pow(0,0)résultat en 1soit utile pour de nombreuses applications, comme l' indique la justification de la Norme internationale - Langages de programmation - C dans la section traitant de la prise en charge arithmétique à virgule flottante CEI 60559 :

Généralement, C99 évite un résultat NaN où une valeur numérique est utile. [...] Les résultats de pow (∞, 0) et pow (0,0) sont tous deux 1, car il existe des applications qui peuvent exploiter cette définition. Par exemple, si x (p) et y (p) sont des fonctions analytiques qui deviennent nulles à p = a, alors pow (x, y), qui est égal à exp (y * log (x)), s'approche de 1 lorsque p approche une.

Mettre à jour C ++

Comme leemes l'a correctement souligné, j'ai initialement lié à la référence pour la version complexe de pow tandis que la version non complexe prétend qu'il s'agit d'une erreur de domaine, le projet de norme C ++ revient au projet de norme C et à la fois C99 et C11 dans la section7.12.7.4 Le paragraphe des fonctions pow 2 dit (c'est moi qui souligne ):

[...] Une erreur de domaine peut se produire si x est zéro et y est zéro. [...]

ce qui, pour autant que je sache, signifie que ce comportement est un comportement non spécifié Remonter un peu la section 7.12.1 Traitement des conditions d'erreur dit:

[...] une erreur de domaine se produit si un argument d'entrée est en dehors du domaine sur lequel la fonction mathématique est définie. [...] En cas d'erreur de domaine, la fonction renvoie une valeur définie par l'implémentation; si l'expression entière math_errhandling & MATH_ERRNO est différente de zéro, l'expression entière errno acquiert la valeur EDOM; [...]

Donc, s'il y avait une erreur de domaine, il s'agirait d'un comportement défini par l'implémentation, mais dans les deux dernières versions de gccet clangla valeur de errnoest 0donc ce n'est pas une erreur de domaine pour ces compilateurs.

Mettre à jour Javascript

Pour Javascript, la spécification du langage ECMAScript® dans la section 15.8 L'objet mathématique sous 15.8.2.13 pow (x, y) dit entre autres conditions que:

Si y est +0, le résultat est 1, même si x est NaN.

Shafik Yaghmour
la source
1
@leemes Je pense que cette page est fausse, la norme ne dit pas que NaN doit être retourné. La valeur de retour est définie par l'implémentation. cplusplus.com qui, selon vous, n'est pas une source fiable est en fait plus précis ici.
entre
@interjay je suppose que vous voulez dire la réponse supprimée; Je n'ai cité que son manque de fiabilité, en espérant que cela pourrait expliquer le vote négatif (ce qui n'était pas de moi). Eh bien, les deux pages sont des wikis, donc leur fiabilité dépend de leurs éditeurs qui sont humains et font des erreurs. ;)
leemes
@leemes la communauté C ++ sur SO a définitivement une forte aversion pour cplusplus.com
Shafik Yaghmour
@ShafikYaghmour J'ai lié la même question (dans la réponse supprimée).
leemes
1
@Alek J'apprécie les commentaires, j'essaie d'écrire les réponses que j'aimerais lire des autres. Je ne réussis pas toujours mais j'essaye. Ecrire de bonnes questions est encore plus difficile, je n'ai essayé qu'une seule fois et j'ai passé beaucoup plus de temps dessus que je le fais sur mes réponses.
Shafik Yaghmour
35

En JavaScript Math.powest défini comme suit :

  • Si y est NaN, le résultat est NaN.
  • Si y est +0, le résultat est 1, même si x est NaN.
  • Si y est −0, le résultat est 1, même si x est NaN.
  • Si x est NaN et y est différent de zéro, le résultat est NaN.
  • Si abs (x)> 1 et y est + ∞, le résultat est + ∞.
  • Si abs (x)> 1 et y vaut −∞, le résultat est +0.
  • Si abs (x) == 1 et y est + ∞, le résultat est NaN.
  • Si abs (x) == 1 et y est −∞, le résultat est NaN.
  • Si abs (x) <1 et y est + ∞, le résultat est +0.
  • Si abs (x) <1 et y est −∞, le résultat est + ∞.
  • Si x est + ∞ et y> 0, le résultat est + ∞.
  • Si x est + ∞ et y <0, le résultat est +0.
  • Si x est −∞ et y> 0 et y est un entier impair, le résultat est −∞.
  • Si x est −∞ et y> 0 et y n'est pas un entier impair, le résultat est + ∞.
  • Si x est −∞ et y <0 et y est un entier impair, le résultat est −0.
  • Si x est −∞ et y <0 et y n'est pas un entier impair, le résultat est +0.
  • Si x est +0 et y> 0, le résultat est +0.
  • Si x est +0 et y <0, le résultat est + ∞.
  • Si x est −0 et y> 0 et y est un entier impair, le résultat est −0.
  • Si x est −0 et y> 0 et y n'est pas un entier impair, le résultat est +0.
  • Si x est −0 et y <0 et y est un entier impair, le résultat est −∞.
  • Si x est −0 et y <0 et y n'est pas un entier impair, le résultat est + ∞.
  • Si x <0 et x est fini et y est fini et y n'est pas un entier, le résultat est NaN.

accent le mien

en règle générale, les fonctions natives de n'importe quelle langue doivent fonctionner comme décrit dans la spécification du langage. Parfois, cela inclut explicitement un «comportement indéfini» où c'est à l'implémenteur de déterminer ce que le résultat devrait être, cependant ce n'est pas un cas de comportement indéfini.

zzzzBov
la source
L'annexe F des normes C99 et C11 contient cette même spécification. Une implémentation est censée définir __STDC_IEC_559__pour annoncer qu'elle est conforme à cette spécification. L'Annexe F décrit l'arithmétique en virgule flottante CEI 60559. Je crois qu'une spécification C est autorisée à se conformer partiellement à l'annexe F (par exemple pow (0, 0) == 1) et ne pas définir __STDC_IEC_559__.
Howard Hinnant
@HowardHinnant hmmm, il semble que dans le cas de gcc and clang, cette information peut ne pas être totalement utile, c'est décourageant.
Shafik Yaghmour
6
Je ne sais pas si cette réponse aide. Bien sûr, la fonction doit fonctionner comme elle est définie dans la spécification. Mais alors la question devient simplement "Pourquoi a-t-il été défini de cette façon dans la spécification?"
Beska
Heureusement que cela est (probablement) fait dans le matériel, sinon cela nuancerait les performances avec tous ces cas spéciaux :)
Thomas
16

C'est juste une convention de le définir comme 1, 0ou de le laisser undefined. La définition pow (0,0)est largement répandue en raison de la définition suivante:

définition de la puissance mathématique


La documentation ECMA-Script dit ce qui suit sur pow(x,y):

  • Si y est +0, le résultat est 1, même si x est NaN.
  • Si y est −0, le résultat est 1, même si x est NaN.

[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13 ]

schmijos
la source
3
math.stackexchange a beaucoup de bonnes discussions et explications pour la définition 0 ^ 0 = 1: math.stackexchange.com/questions/11150/…
PLL
14

Selon Wikipedia:

Dans la plupart des contextes n'impliquant pas de continuité dans l'exposant, interpréter 0 0 comme 1 simplifie les formules et élimine le besoin de cas particuliers dans les théorèmes.

Il existe plusieurs façons de traiter 0**0chacune avec des avantages et des inconvénients (voir Wikipedia pour une discussion approfondie).

La norme à virgule flottante IEEE 754-2008 recommande trois fonctions différentes:

  • pow friandises 0**0 comme 1. Il s'agit de la version la plus ancienne définie. Si la puissance est un entier exact, le résultat est le même que pour pown, sinon le résultat est comme pour powr(sauf dans certains cas exceptionnels).
  • powntraite 0 ** 0 comme 1. La puissance doit être un entier exact. La valeur est définie pour les bases négatives; par exemple, pown(−3,5)est −243.
  • powrtraite 0 ** 0 comme NaN (Not-a-Number - non défini). La valeur est également NaN pour les cas comme powr(−3,2)où la base est inférieure à zéro. La valeur est définie par exp (puissance '× log (base)).
NPE
la source
6

Donald Knuth

en quelque sorte réglé ce débat en 1992 avec ce qui suit:

entrez la description de l'image ici

Et est allé encore plus dans les détails dans son article Two Notes on Notation .

Fondamentalement, bien que nous n'ayons pas 1 comme limite de f(x)/g(x)pour toutes les fonctions pas toutes f(x)et g(x), cela rend la combinatoire tellement plus simple à définir 0^0=1, puis faites simplement des cas spéciaux aux quelques endroits où vous devez considérer des fonctions telles que 0^x, qui sont bizarres de toute façon. Après tout, cela x^0revient beaucoup plus souvent.

Certaines des meilleures discussions que je connaisse sur ce sujet (autres que l'article de Knuth) sont:

Thomas Ahle
la source
Si vous n'en avez pas lu, lisez les réponses en Zéro à la puissance zéro ...? qui était liée à la question vous devriez certaines des réponses couvrent également cette approche.
Shafik Yaghmour
5

Lorsque vous voulez savoir à quelle valeur vous devez donner f(a)quand fn'est pas directement calculable a, vous calculez la limite de fquand xtend versa .

Dans le cas de x^y, les limites habituelles tendent vers 1quand xet ytendent vers 0, et surtout x^xvers 1quand xtend vers 0.

Voir http://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml

Denys Séguret
la source
5

La définition du langage C dit (7.12.7.4/2):

Une erreur de domaine peut se produire si x est égal à zéro et y est égal à zéro.

Il dit aussi (7.12.1 / 2):

En cas d'erreur de domaine, la fonction renvoie une valeur définie par l'implémentation; si l'expression entière math_errhandling & MATH_ERRNO est différente de zéro, l'expression entière errno acquiert la valeur EDOM; si l'expression entière math_errhandling & MATH_ERREXCEPT est différente de zéro, l'exception à virgule flottante «invalide» est déclenchée.

Par défaut, la valeur de math_errhandlingest MATH_ERRNO, alors vérifiez errnola valeur EDOM.

Pete Becker
la source
1
Whoups! C'est vraiment intéressant! J'ai compilé mon fichier cpp en utilisantg++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.
Ionică Bizău
0

Je ne suis pas d'accord avec certaines des réponses précédentes affirmant que c'est une question de convention ou de commodité (couvrant certains cas spéciaux pour divers théorèmes, etc.) que 0 ^ 0 soit défini comme 1 au lieu de 0.

L'exponentiation ne correspond pas vraiment à nos autres notations mathématiques, donc la définition que nous apprenons tous laisse place à la confusion. Une manière légèrement différente de l'aborder est de dire que a ^ b (ou exp (a, b), si vous voulez) renvoie la valeur multiplicative équivalente à la multiplication d' une autre chose par a, répétée b fois.

Lorsque nous multiplions 5 par 4, 2 fois, nous obtenons 80. Nous avons multiplié 5 par 16. Donc 4 ^ 2 = 16.

Lorsque vous multipliez 14 par 0, 0 fois, il nous reste 14. Nous l'avons multiplié par 1. Par conséquent, 0 ^ 0 = 1.

Cette ligne de pensée pourrait également aider à clarifier les exposants négatifs et fractionnaires. 4 ^ (- 2) est un 16e, car «multiplication négative» est une division - nous divisons par quatre deux fois.

a ^ (1/2) est la racine (a), car multiplier quelque chose par la racine de a est la moitié du travail multiplicatif que le multiplier par un lui-même - il faudrait le faire deux fois pour multiplier quelque chose par 4 = 4 ^ 1 = (4 ^ (1/2)) ^ 2

NiloCK
la source
0

Pour cela, vous devez résoudre le calcul:

entrez la description de l'image ici

En développant x^xautour de zéro en utilisant la série Taylor, nous obtenons:

entrez la description de l'image ici

Donc, pour comprendre ce qui se passe avec la limite quand xva à zéro, nous devons savoir ce qui se passe avec le deuxième mandat x log(x), car les autres termes sontx log(x) une certaine puissance.

Nous devons utiliser la transformation:

entrez la description de l'image ici

Maintenant, après cette transformation, nous pouvons utiliser la règle de L'Hôpital , qui stipule que:

entrez la description de l'image ici

Si nous différencions cette transformation, nous obtenons:

entrez la description de l'image ici

Nous avons donc calculé que le terme log(x)*xs'approche de 0 lorsque x s'approche de 0. Il est facile de voir que d'autres termes consécutifs se rapprochent également de zéro et même plus rapidement que le second terme.

Donc au point x=0, la série devient 1 + 0 + 0 + 0 + ...et donc égale à 1.

Agnius Vasiliauskas
la source
Bien que cette réponse soit impressionnante, il convient de noter qu'en mathématiques, la limite en tant que x-> a de f (x) n'est pas nécessairement égale à f (a), sauf si la fonction est continue en x.
jasonszhao