2017-06-28 3 views
1

Ich habe einen Fehler in meinem Programm gefunden, der die Umordnungsmethode ausführt, um die Wurzeln von Gleichungen zu finden.Zwei verschiedene Antworten, wenn sie mathematisch gleich sind ..?

Ich habe bemerkt, dass Python zwei verschiedene Antworten auf Konsolen basierend produziert. Zum Beispiel

-4**(1/3) = -1.5874010519681994 
-4.0**(1/3) = -1.5874010519681994 
(-4)**(1/3) = (0.7937005259840999+1.3747296369986024j) 
(-4.0)**(1/3) = (0.7937005259840999+1.3747296369986024j) 

Ich habe -4,0 eine Variablen x zugewiesen und dann x ** (1/3) y zuweisen, aber ich die komplexe Zahl anstelle der tatsächlichen Antwort.

Warum ist das? Gibt es eine einfache Möglichkeit, dies zu verhindern?

Dank

Antwort

3

Es gibt zwei Dinge in Ihren Beispielen geht.

Zunächst werden die Klammern um die -4 Angelegenheiten, da die Potenzierung vor der Negation in der Reihenfolge der Operationen erfolgt. Daher wird in den ersten beiden Beispielen die Kraft zuerst gemacht, dann wird das Ergebnis der Kraft negativ genommen. Dies ist, was Sie erwartet haben, so dass Sie dies nicht abgefragt haben, aber das hat nicht die Cube-Wurzel von -4, sondern das Negative der Cube-Wurzel von 4 genommen.

Das zweite Problem ist, dass die meisten Gleitkomma-Arithmetik in Python ist nicht exakt. Das Ergebnis von 1/3 ist kein Bruch, sondern eine Fließkommazahl. Wenn Sie die as_integer_ratio Methode auf eine Variable Speichern des Werts von 1/3 verwenden Sie das Ergebnis erhalten

(6004799503160661, 18014398509481984) 

zeigt, dass es nicht wirklich 1 über 3. Daher ist, etwas an die Macht der 1/3 Einnahme ist nicht das Gleiche wie unter seine Kubikwurzel, da keine solche Fraktion tatsächlich beteiligt ist. Python interpretiert den Exponenten als einen realen Wert, nicht einen rationalen Wert, und für negative Zahlen als Basis des Wert von x**y als exp(y*ln(x)) interpretiert wird, wie in der Mathematik durchgeführt wird. Der Logarithmus einer negativen reellen Zahl ist eine komplexe Zahl, so dass das Endergebnis ebenfalls komplex ist.

Wenn Sie tatsächlich die Kubikwurzel -4 wollen könnten Sie einfach Ihre Berechnung wie in den ersten beiden Beispielen schreiben. Wenn Sie Wurzeln möglicherweise negativer Zahlen nehmen wollen im Allgemeinen Sie eine Routine, mit der Definition schreiben konnten

def power_frac(base, numerator, denominator): 
    """Return base**(numerator/denominator) where base is a 
    floating-point number and both numerator and denominator are 
    integers. 
    """ 

Diese Funktion müßte für viele Fälle überprüfen, da (zum Beispiel) eine noch Wurzel eines negativen Nummer ist nicht real. Aber das könnte gemacht werden. Ich glaube nicht, dass eine solche Funktion in Python integriert ist. Denken Sie daran, dass der Exponent als zwei ganze Zahlen (oder ein Bruchwert) angegeben werden muss, da Python den genauen Bruch, den Sie meinen, wenn Sie den Exponenten als Gleitkomma-Division berechnen, nicht herausfinden kann.

Wenn Sie nur einen Würfel Wurzel jeder reelle Zahl wollen, könnten Sie

def cuberoot(x): 
    return x**(1/3) if x >= 0 else -(-x)**(1/3) 
+0

Danke, das ist eine ausführlichere Erklärung als meine eigene Antwort! – tzaman

+0

Das hat nichts mit der Rationalität von '1/3' zu tun. Die Potenzfunktion 'x ** y 'ist entweder nur für das positive' x 'im reellen Zahlenkontext oder für alle' x 'mit der von Ihnen angegebenen Formel oder einer Verfeinerung in einem komplexen Zahlenkontext definiert. Die komplexe Kubikwurzel ist definiert als die Wurzel mit dem kleinsten Winkel, das numerische Ergebnis wird nicht durch die Differenz von "1/3" und "0.3333 ... 334" beeinflusst. – LutzL

+0

Reellwertige Potenzierung wird oft auf diese Weise definiert: 'x ** (m/n)' ist für 'x' reell und' m' und 'n' ganze Zahlen und' n' positiv, die 'n'te Wurzel von 'x ** m' wenn es existiert - wenn mehr als eine solche Wurzel in den reellen Zahlen existiert, wähle die positive Wurzel. Die Frage und meine Antwort basieren auf dieser gemeinsamen Definition. Ihre Definition existiert auch, wird aber für nicht-rationale Exponenten verwendet. Die Potenzierung ist eine der wenigen echten Operationen, die vom Typ ihrer Argumente abhängt. Leugnen Sie, dass meine Definition oft verwendet wird? –

2

Dies ist kein Fehler, dann ist es eine Frage der Operator Vorrang. Wenn Sie the docs überprüfen, sehen Sie, dass der Minusoperator - eine niedrigere Priorität hat als der Exponentiationsoperator **. So Ihre erste Ausdruck ist:

- (4 ** (1/3)) 

Und das zweite ist:

(-4) ** (1/3) 

das ist nicht dasselbe überhaupt.

+0

Okay, verwenden, aber wie würde ich dieses Problem umgehen, wenn x = -4,0 und dann ich tun x ** (1/3) –

+0

Sollte nicht (-4) ** (1/3) das gleiche wie die erste Gleichung ergeben, macht der Rechner –

+0

@SylentNyte: Ihr Rechner (wie der TI-Nspire CX) berechnet fast sicher '1/3' als Rational-Typ oder dergleichen. Wie fast alle Computersprachen berechnet Python '1/3' als Fließkommazahl, was nicht dasselbe ist (siehe meine Antwort). –

Verwandte Themen