Perché Math.pow (0, 0) === 1?


85

Sappiamo tutti che 0 0 è indeterminato.

Tuttavia , javascript dice che:

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

e C ++ dice la stessa cosa:

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

PERCHÉ?

Lo so:

>Math.pow(0.001, 0.001)
0.9931160484209338

Ma perché non Math.pow(0, 0)genera errori? O forse NaNsarebbe meglio di 1.


3
@zzzzBov: secondo la definizione standard, "a <sup> b </sup> = exp (b ln (a))", non è definito. Cercare di definirlo come "limite <sub> x-> 0 </sub> f (x) <sup> g (x) </sup>" dove "f" e "g" hanno entrambi limiti pari a zero dà un indeterminato valore, poiché dipende dalla scelta delle funzioni. (Mi scuso per la notazione alterata; non riesco a capire come ottenere apici nei commenti).
Mike Seymour

@MikeSeymour, sì, sono consapevole che 0⁰ (usa caratteri Unicode) non è definito data quella definizione, tuttavia, se leggi il mio commento dovresti notare che la citazione fa riferimento al "mondo della matematica" piuttosto che a qualsiasi "definizione standard". È questa differenza a cui mi riferivo originariamente e la domanda è stata aggiornata per correggere questa sfumatura.
zzzzBov

2
@AJMansfield Um ... a ^ 0 = 1 per diverso da zero a.
Beska

Consente alle funzioni che dipendono dai prodotti delle probabilità di fornire risultati ragionevoli. È un'idea sbagliata che i computer siano processori matematici simbolici. Il linguaggio C ha un'implementazione specifica nel mondo reale mentre il tuo mondo matematico potrebbe essere troppo ideale per essere implementato in silicio.
IRTFM

26
Per la versione matematica di questa domanda: "perché spesso definiamo 0 ^ 0 = 1?" - math.stackexchange ha molte buone risposte: math.stackexchange.com/questions/11150/…
PLL

Risposte:


78

In C ++ Il risultato di pow (0, 0) il risultato è fondamentalmente un comportamento definito dall'implementazione poiché matematicamente abbiamo una situazione contraddittoria in cui N^0dovrebbe essere sempre 1ma 0^Ndovrebbe sempre essere 0per N > 0, quindi non dovresti avere aspettative matematicamente sul risultato di questo. Questo post del forum Wolfram Alpha fornisce maggiori dettagli.

Sebbene il pow(0,0)risultato 1sia utile per molte applicazioni, poiché il Rationale for International Standard — Programming Languages ​​— C afferma nella sezione relativa al supporto aritmetico a virgola mobile IEC 60559 :

In genere, C99 evita un risultato NaN dove è utile un valore numerico. [...] I risultati di pow (∞, 0) e pow (0,0) sono entrambi 1, perché ci sono applicazioni che possono sfruttare questa definizione. Ad esempio, se x (p) e y (p) sono funzioni analitiche che diventano zero in p = a, allora pow (x, y), che è uguale a exp (y * log (x)), si avvicina a 1 quando p si avvicina un.

Aggiorna C ++

Come i leemes hanno correttamente sottolineato, originariamente mi collegavo al riferimento per la versione complessa di pow mentre la versione non complessa afferma che è un errore di dominio la bozza dello standard C ++ ricade sulla bozza dello standard C e sia C99 che C11 nella sezione 7.12.7.4 Il paragrafo funzioni pow 2 dice ( enfasi mia ):

[...] Può verificarsi un errore di dominio se x è zero ey è zero. [...]

che, per quanto posso dire mezzo questo comportamento è un comportamento non specificato di avvolgimento di una sezione po ' 7.12.1 Trattamento delle condizioni di errore dice:

[...] si verifica un errore di dominio se un argomento di input è esterno al dominio su cui è definita la funzione matematica [...] In un errore di dominio, la funzione restituisce un valore definito dall'implementazione; se l'espressione intera math_errhandling & MATH_ERRNO è diversa da zero, l'espressione intera errno acquisisce il valore EDOM; [...]

Quindi, se ci fosse un errore di dominio, questo sarebbe un comportamento definito dall'implementazione, ma sia nelle ultime versioni di gccche clangnel valore di errnoè 0quindi non è un errore di dominio per quei compilatori.

Aggiorna Javascript

Per Javascript, la specifica del linguaggio ECMAScript® nella sezione 15.8 The Math Object in 15.8.2.13 pow (x, y) dice tra le altre condizioni che:

Se y è +0, il risultato è 1, anche se x è NaN.


1
@leemes Credo che la pagina sia sbagliata, lo standard non dice che NaN dovrebbe essere restituito. Il valore restituito è definito dall'implementazione. cplusplus.com che sostieni non sia una fonte affidabile è in realtà più preciso qui.
Interjay

@interjay Immagino tu intenda la risposta cancellata; Ho solo citato la sua inaffidabilità, sperando che potesse spiegare il voto negativo (che non era da me). Ebbene, entrambe le pagine sono wiki, quindi la loro affidabilità dipende dai loro editor che sono umani e commettono errori. ;)
leemes


@ ShafikYaghmour Ho collegato la stessa domanda (nella risposta eliminata).
leemes

1
@ Alek Apprezzo il feedback, cerco di scrivere le risposte che vorrei leggere dagli altri. Non sempre ci riesco ma ci provo. Scrivere buone domande è ancora più difficile, ci ho provato solo una volta e ci ho dedicato molto più tempo che nelle mie risposte.
Shafik Yaghmour

35

In JavaScript Math.powè definito come segue :

  • Se y è NaN, il risultato è NaN.
  • Se y è +0, il risultato è 1, anche se x è NaN.
  • Se y è −0, il risultato è 1, anche se x è NaN.
  • Se x è NaN ey è diverso da zero, il risultato è NaN.
  • Se abs (x)> 1 ey è + ∞, il risultato è + ∞.
  • Se abs (x)> 1 ey è −∞, il risultato è +0.
  • Se abs (x) == 1 ey è + ∞, il risultato è NaN.
  • Se abs (x) == 1 e y è −∞, il risultato è NaN.
  • Se abs (x) <1 ey è + ∞, il risultato è +0.
  • Se abs (x) <1 ey è −∞, il risultato è + ∞.
  • Se x è + ∞ e y> 0, il risultato è + ∞.
  • Se x è + ∞ ey <0, il risultato è +0.
  • Se x è −∞ ey> 0 e y è un numero intero dispari, il risultato è −∞.
  • Se x è −∞ e y> 0 e y non è un numero intero dispari, il risultato è + ∞.
  • Se x è −∞ ey <0 e y è un numero intero dispari, il risultato è −0.
  • Se x è −∞ ey <0 e y non è un numero intero dispari, il risultato è +0.
  • Se x è +0 e y> 0, il risultato è +0.
  • Se x è +0 ey <0, il risultato è + ∞.
  • Se x è −0 e y> 0 e y è un numero intero dispari, il risultato è −0.
  • Se x è −0 e y> 0 e y non è un numero intero dispari, il risultato è +0.
  • Se x è −0 ey <0 e y è un numero intero dispari, il risultato è −∞.
  • Se x è −0 ey <0 e y non è un numero intero dispari, il risultato è + ∞.
  • Se x <0 e x è finito ey è finito ey non è un numero intero, il risultato è NaN.

enfasi mia

come regola generale, le funzioni native di qualsiasi lingua dovrebbero funzionare come descritto nella specifica della lingua. A volte questo include esplicitamente "comportamento indefinito" in cui spetta all'implementatore determinare quale dovrebbe essere il risultato, tuttavia questo non è un caso di comportamento indefinito.


L'allegato F delle norme C99 e C11 contiene la stessa specifica. Si suppone che un'implementazione definisca __STDC_IEC_559__per annunciare che è conforme a questa specifica. L'allegato F descrive l'aritmetica in virgola mobile IEC 60559. Credo che una specifica C possa essere parzialmente conforme all'Allegato F (ad esempio pow (0, 0) == 1) e non definire __STDC_IEC_559__.
Howard Hinnant

@HowardHinnant hmmm, sembra che nel caso di gcc e clang quell'informazione potrebbe non essere del tutto utile, il che è scoraggiante.
Shafik Yaghmour

6
Non so se questa risposta aiuti. Ovviamente la funzione dovrebbe funzionare come definito nelle specifiche. Ma poi la domanda diventa semplicemente "Perché è stato definito in questo modo nelle specifiche?"
Beska

Meno male che questo è (probabilmente) fatto nell'hardware, altrimenti potrebbe nuocere alle prestazioni con tutti questi casi speciali :)
Thomas

16

È solo convenzione definirlo come 1, 0o lasciarlo undefined. La definizione pow (0,0)è molto diffusa a causa della seguente definizione:

definizione di potenza matematica


La documentazione di ECMA-Script dice quanto segue su pow(x,y):

  • Se y è +0, il risultato è 1, anche se x è NaN.
  • Se y è −0, il risultato è 1, anche se x è NaN.

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


3
math.stackexchange ha molte buone discussioni e spiegazioni per la definizione 0 ^ 0 = 1: math.stackexchange.com/questions/11150/…
PLL

14

Secondo Wikipedia:

Nella maggior parte delle impostazioni che non implicano continuità nell'esponente, interpretare 0 0 come 1 semplifica le formule ed elimina la necessità di casi speciali nei teoremi.

Ci sono diversi modi possibili per trattare 0**0con pro e contro per ciascuno (vedi Wikipedia per una discussione estesa).

Lo standard a virgola mobile IEEE 754-2008 consiglia tre diverse funzioni:

  • powtratta 0**0come 1. Questa è la versione definita più vecchia. Se la potenza è un intero esatto il risultato è lo stesso di pown, altrimenti il ​​risultato è come powr(salvo alcuni casi eccezionali).
  • pownconsidera 0 ** 0 come 1. La potenza deve essere un numero intero esatto. Il valore è definito per basi negative; ad esempio, pown(−3,5)è −243.
  • powrconsidera 0 ** 0 come NaN (Not-a-Number - undefined). Il valore è anche NaN per casi come powr(−3,2)dove la base è minore di zero. Il valore è definito da exp (power '× log (base)).

6

Donald Knuth

ha risolto questo dibattito nel 1992 con quanto segue:

inserisci qui la descrizione dell'immagine

Ed è andato ancora più nei dettagli nel suo articolo Two Notes on Notation .

Fondamentalmente, anche se non abbiamo 1 come limite f(x)/g(x)per tutte non tutte le funzioni f(x)e g(x), rende comunque la combinatoria molto più semplice da definire 0^0=1, e quindi crea casi speciali nei pochi posti in cui è necessario considerare funzioni come 0^x, quale sono strani comunque. Dopotutto x^0viene fuori molto più spesso.

Alcune delle migliori discussioni che conosco su questo argomento (oltre al documento di Knuth) sono:


Se non ne hai lette alcune leggi le risposte in Zero alla potenza zero ...? che è stato collegato alla domanda dovresti alcune delle risposte coprono anche questo approccio.
Shafik Yaghmour


5

La definizione del linguaggio C dice (7.12.7.4/2):

Può verificarsi un errore di dominio se x è zero ey è zero.

Dice anche (7.12.1 / 2):

In caso di errore di dominio, la funzione restituisce un valore definito dall'implementazione; se l'espressione intera math_errhandling & MATH_ERRNO è diversa da zero, l'espressione intera errno acquisisce il valore EDOM; se l'espressione intera math_errhandling & MATH_ERREXCEPT è diverso da zero, viene sollevata l'eccezione a virgola mobile "non valida".

Per impostazione predefinita, il valore di math_errhandlingè MATH_ERRNO, quindi controlla errnoil valore EDOM.


1
Whoups! È davvero interessante! Ho compilato il mio file cpp usandog++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.
Ionică Bizău

0

Vorrei essere in disaccordo con l'affermazione di alcune delle risposte precedenti secondo cui è una questione di convenzione o convenienza (coprendo alcuni casi speciali per vari teoremi, ecc.) Che 0 ^ 0 sia definito come 1 invece di 0.

L'esponenziazione in realtà non si adatta così bene alle nostre altre notazioni matematiche, quindi la definizione che impariamo tutti lascia spazio alla confusione. Un modo leggermente diverso di avvicinarsi è dire che a ^ b (o exp (a, b), se preferisci) restituisce il valore moltiplicativamente equivalente a moltiplicare qualche altra cosa per a, ripetuto b volte.

Quando moltiplichiamo 5 per 4, 2 volte, otteniamo 80. Abbiamo moltiplicato 5 per 16. Quindi 4 ^ 2 = 16.

Quando moltiplichi 14 per 0, 0 volte, ci rimane 14. Lo abbiamo moltiplicato 1. Quindi, 0 ^ 0 = 1.

Questa linea di pensiero potrebbe anche aiutare a chiarire esponenti negativi e frazionari. 4 ^ (- 2) è un sedicesimo, perché la "moltiplicazione negativa" è la divisione: dividiamo per quattro due volte.

a ^ (1/2) è la radice (a), perché moltiplicare qualcosa per la radice di a è metà del lavoro moltiplicativo come moltiplicarlo per a se stesso - dovresti farlo due volte per moltiplicare qualcosa per 4 = 4 ^ 1 = (4 ^ (1/2)) ^ 2


0

Per questo per capire è necessario risolvere il calcolo:

inserisci qui la descrizione dell'immagine

Espandendoci x^xintorno allo zero usando la serie Taylor, otteniamo:

inserisci qui la descrizione dell'immagine

Quindi per capire cosa sta succedendo con limite quando xva a zero, dobbiamo scoprire cosa sta succedendo con il secondo mandato x log(x), perché gli altri termini sono proporzionali ax log(x) a una certa potenza.

Dobbiamo usare la trasformazione:

inserisci qui la descrizione dell'immagine

Ora dopo questa trasformazione possiamo usare la regola di L'Hôpital , che afferma che:

inserisci qui la descrizione dell'immagine

Quindi differenziando quella trasformazione otteniamo:

inserisci qui la descrizione dell'immagine

Quindi abbiamo calcolato quel termine log(x)*x avvicina a 0 quando x si avvicina a 0. È facile vedere che anche altri termini consecutivi si avvicinano a zero e anche più velocemente del secondo termine.

Quindi, al punto x=0, la serie diventa 1 + 0 + 0 + 0 + ...e quindi è uguale a 1.


Sebbene questa risposta sia impressionante, vale la pena notare che in matematica, il limite come x-> a di f (x) non è necessariamente uguale a f (a), a meno che la funzione non sia continua in x.
jasonszhao
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.