Wir alle wissen, dass 0 0 unbestimmt ist.
Aber , Javascript , sagt , dass:
Math.pow(0, 0) === 1 // true
und C ++ sagt dasselbe:
pow(0, 0) == 1 // true
WARUM?
Ich weiß das:
>Math.pow(0.001, 0.001)
0.9931160484209338
Aber warum Math.pow(0, 0)
wirft man keine Fehler? Oder vielleicht NaN
wäre ein besser als 1
.
javascript
c++
language-agnostic
pow
Ionică Bizău
quelle
quelle
Antworten:
In C ++
Das Ergebnis der pow (0, 0)ist das Ergebnis grundsätzlich Implementierung Verhalten definiert , da mathematisch haben wir eine widersprüchliche Situation , woN^0
immer sein soll ,1
sondern0^N
sollte immer sein ,0
fürN > 0
, so dass Sie keine Erwartungen mathematisch als auf das Ergebnis dieser entweder haben sollten. Dieser Wolfram Alpha Forenbeiträge gehen auf etwas mehr Details ein.Obwohl das
pow(0,0)
Ergebnis in1
für viele Anwendungen nützlich ist, wie in der Begründung für den internationalen Standard - Programmiersprachen - C im Abschnitt über die Gleitkomma-Arithmetikunterstützung nach IEC 60559 angegeben :Aktualisieren Sie C ++
Wie Leemes richtig hervorhob, habe ich ursprünglich auf die Referenz für die komplexe Version von pow verwiesen, während die nicht komplexe Version behauptet, es handele sich um einen Domänenfehler. Der Entwurf des C ++ - Standards greift auf den Entwurf des C-Standards zurück und sowohl auf C99 als auch auf C11 im Abschnitt Absatz der
7.12.7.4
pow-Funktionen 2 sagt ( Hervorhebung von mir ):die, soweit ich das beurteilen kann mittels dieses Verhalten ist nicht spezifiziert Verhalten ein wenig Abschnitt Winding zurück
7.12.1
Behandlung von Fehlerzuständen , sagt:Wenn also ein Domänenfehler aufgetreten wäre, wäre dies ein implementierungsdefiniertes Verhalten, aber sowohl in den neuesten Versionen
gcc
als auchclang
im Wert vonerrno
ist0
es kein Domänenfehler für diese Compiler.Aktualisieren Sie Javascript
Für Javascript gibt die ECMAScript®-Sprachspezifikation im Abschnitt
15.8
Das mathematische Objekt unter15.8.2.13
pow (x, y) unter anderem Folgendes an:quelle
In JavaScript
Math.pow
ist wie folgt definiert :Betonung meiner
In der Regel sollten native Funktionen für jede Sprache wie in der Sprachspezifikation beschrieben funktionieren. Manchmal schließt dies explizit "undefiniertes Verhalten" ein, wobei es Sache des Implementierers ist, zu bestimmen, wie das Ergebnis aussehen soll. Dies ist jedoch kein Fall von undefiniertem Verhalten.
quelle
__STDC_IEC_559__
, dass sie dieser Spezifikation entspricht. Anhang F beschreibt die Gleitkomma-Arithmetik nach IEC 60559. Ich glaube, eine C-Spezifikation darf teilweise Anhang F entsprechen (z. B. pow (0, 0) == 1) und nicht definieren__STDC_IEC_559__
.Es ist nur Konvention zu definieren es als
1
,0
oder es zu verlassenundefined
. Die Definition ist aufgrund der folgenden Definition weit verbreitet:In der ECMA-Script-Dokumentation wird Folgendes angegeben
pow(x,y)
:[ http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.2.13 ]
quelle
Laut Wikipedia:
Es gibt verschiedene Möglichkeiten,
0**0
mit Vor- und Nachteilen umzugehen (siehe Wikipedia für eine ausführliche Diskussion).Der Gleitkomma-Standard IEEE 754-2008 empfiehlt drei verschiedene Funktionen:
pow
behandelt0**0
als1
. Dies ist die älteste definierte Version. Wenn die Potenz eine exakte Ganzzahl ist, ist das Ergebnis das gleiche wie fürpown
, andernfalls ist das Ergebnis wie fürpowr
(mit Ausnahme einiger Ausnahmefälle).pown
behandelt 0 ** 0 als 1. Die Potenz muss eine exakte ganze Zahl sein. Der Wert ist für negative Basen definiert; zBpown(−3,5)
ist−243
.powr
behandelt 0 ** 0 als NaN (Not-a-Number - undefined). Der Wert ist auch NaN für Fälle, inpowr(−3,2)
denen die Basis kleiner als Null ist. Der Wert wird durch exp (Leistung '× log (Basis)) definiert.quelle
Donald Knuth
Diese Debatte wurde 1992 mit folgenden Mitteln beigelegt:
Und ging in seiner Arbeit Two Notes on Notation noch näher auf Details ein .
Grundsätzlich haben wir zwar nicht 1 als Grenze
f(x)/g(x)
für alle, nicht alle Funktionenf(x)
undg(x)
, aber es macht die Kombinatorik immer noch so viel einfacher zu definieren0^0=1
und dann nur Sonderfälle an den wenigen Stellen, an denen Sie Funktionen wie z. B.0^x
welche berücksichtigen müssen sind sowieso komisch. Immerhinx^0
kommt viel öfter auf.Einige der besten Diskussionen, die ich zu diesem Thema kenne (außer dem Knuth-Papier), sind:
quelle
Wenn Sie wissen möchten , welchen Wert sollten Sie geben ,
f(a)
wennf
nicht direkt berechenbar ista
, berechnen Sie die Grenze ,f
wennx
zustrebta
.Im Falle von
x^y
tendieren die üblichen Grenzen dazu,1
wannx
und zuy
tendieren0
, undx^x
tendieren insbesondere dazu,1
wannx
dazu tendiert0
.Siehe http://www.math.hmc.edu/funfacts/ffiles/10005.3-5.shtml
quelle
Die C-Sprachdefinition lautet (7.12.7.4/2):
Es heißt auch (7.12.1 / 2):
Standardmäßig ist der Wert von
math_errhandling
ISMATH_ERRNO
zu überprüfen, alsoerrno
für den WertEDOM
.quelle
g++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.
Ich möchte mit der Behauptung einiger der vorherigen Antworten nicht einverstanden sein, dass es eine Frage der Konvention oder der Zweckmäßigkeit ist (einige Sonderfälle für verschiedene Theoreme usw.), dass 0 ^ 0 als 1 anstelle von 0 definiert wird.
Die Potenzierung passt nicht so gut zu unseren anderen mathematischen Notationen, daher lässt die Definition, die wir alle lernen, Raum für Verwirrung. Eine etwas andere Herangehensweise besteht darin, zu sagen, dass a ^ b (oder exp (a, b), wenn Sie möchten) den Wert zurückgibt multiplikativ äquivalent zum Multiplizieren einer anderen Sache mit a wiederholt b-mal .
Wenn wir 5 mit 4, 2 mal multiplizieren, erhalten wir 80. Wir haben 5 mit 16 multipliziert. Also 4 ^ 2 = 16.
Wenn Sie 14 mit 0, 0 mal multiplizieren, bleibt 14 übrig. Wir haben es mit 1 multipliziert. Daher ist 0 ^ 0 = 1.
Diese Denkweise könnte auch dazu beitragen, negative und gebrochene Exponenten zu klären. 4 ^ (- 2) ist ein 16., weil 'negative Multiplikation' Division ist - wir teilen zweimal durch vier.
a ^ (1/2) ist Wurzel (a), weil das Multiplizieren von etwas mit der Wurzel von a die Hälfte der multiplikativen Arbeit ist, als das Multiplizieren mit a selbst - Sie müssten es zweimal tun, um etwas mit 4 = 4 ^ 1 = zu multiplizieren (4 ^ (1/2)) ^ 2
quelle
Damit dies verstanden wird, müssen Sie den Kalkül lösen:
Wenn
x^x
wir mit Taylor-Reihen um Null expandieren, erhalten wir:Um zu verstehen, was mit dem Limit los ist, wenn es
x
auf Null geht, müssen wir herausfinden, was mit dem zweiten Term los istx log(x)
, da andere Terme proportional zu sindx log(x)
einer gewissen Potenz sind.Wir müssen Transformation verwenden:
Nach dieser Transformation können wir nun die Regel von L'Hôpital verwenden , die besagt:
So differenzieren wir diese Transformation, die wir bekommen:
Also haben wir diesen Begriff berechnet
log(x)*x
0 nähert, wenn sich x 0 nähert. Es ist leicht zu erkennen, dass andere aufeinanderfolgende Terme sich ebenfalls Null nähern und sogar schneller als der zweite Term sind.An diesem Punkt
x=0
wird die Reihe1 + 0 + 0 + 0 + ...
und ist somit gleich 1.quelle