Wie kann ich die Lösung einer komplizierten Gleichung erhalten?
Einführung
Update 6/2014
Ursprünglich habe ich drei Lösungen gefunden; jetzt sind es sechs. Ich dachte, ich wüsste, dass es drei gibt, weil die Rationalisierung der Gleichung zu einem Polynom vom Grad 24 führt und NSolve
24 Wurzeln findet und dann Wurzeln eliminiert, die keine Nullen der ursprünglichen Gleichung waren. Es stellt sich heraus, dass die Gleichung aus numerischer Sicht problematisch war und ich drei verpasst habe.
Andere Modifikationen:
-
Es scheint natürlicher zu sein,
Rationalize
zu verwenden, um die Koeffizienten in diesem Fall in exakte Zahlen umzuwandeln, alsSetPrecision
. -
Ebenso habe ich
First @ eq
durchSubtract @@ eq
ersetzt.
Rationalisieren Sie die Gleichung
Man sollte bedenken, dass gemäß der Dokumentation über NSolve
NSolve
beschäftigt sich hauptsächlich mit linearen und polynomischen Gleichungen.
Die OP-Gleichung ist eine algebraische Gleichung, die in eine Polynomgleichung umgewandelt werden kann, die NSolve
dann leicht lösen kann. Da NSolve
dies nicht alleine tut, müssen wir “von Hand” rationalisieren.” Rationalisierung führt tendenziell zu Fremdlösungen, daher müssen wir die von NSolve
zurückgegebenen Antworten überprüfen. Die etwas fiesen Koeffizienten von eq
erschweren es, da bei der Rationalisierung von eq
ein Rundungsfehler dazu führt, dass einige der Quadratwurzeln nicht wie gewünscht aufgehoben werden. Wir können das beheben, indem wir die Genauigkeit von eq
auf Infinity
.
Wir können die Quadratwurzeln in einem Ausdruck expr
mit
DeleteDuplicates @ Cases, Infinity]
Dann können wir für jede Quadratwurzel expr
mit dem Ausdruck multiplizieren, wobei die Quadratwurzel durch ihr Negativ ersetzt und vereinfacht wird.
Unten ist das Ergebnis der Anwendung der Methode auf die Funktion, die durch Ersetzen von Equal
in eq
durch Subtract
durch Apply
(@@
) erhalten wird. Wir können die Gleichung genau lösen.
eqExact = Rationalize;rationalized = Simplify @ Fold &, eqExact, DeleteDuplicates@Cases, Infinity]];rootsRatExact = Solve;rootsRat = NSolve(* 24 roots {{ζ -> -24559.6 + 24559.6 I}, <<22>>, {ζ -> 24559.6 - 24559.7 I}}*)
Es gibt einige signifikante Unterschiede zwischen den beiden Lösungen:
(ζ /. rootsRat) - (ζ /. rootsRatExact) // Abs // Max(* 3.15226*10^-10*)
Auswählen der Wurzeln der gegebenen Gleichung
Update: Hier habe ich einige Nullen verpasst.
Ich habe Pick
verwendet, um Wurzeln auszuwählen, bei denen die ursprüngliche Gleichung eq
einen kleinen Wert hat, der unter einem kleinen Schwellenwert liegt, z. B. 10^-1
. Wir können später überprüfen, ob jeder eine Wurzel ist, aber ich habe nicht nach anderen Wurzeln gesucht. Die ursprünglichen Wurzeln waren:
rootsEq = Pick < 10^-1 /. rootsRat](* {{ζ -> -3.78042 - 5.50655 I}, {ζ -> -3.20562 + 5.39914 I}, {ζ -> 6.98478 + 0.493405 I}}*)
Diese entsprechen den Wurzeln 7, 9 und 20 in rootsRat
:
Position < 10^-1 &)](* {{7}, {9}, {20}}*)
Wenn ich die genaue Gleichung mit PossibleZeroQ
auf Nullen überprüfe, erhalte ich mehr Wurzeln:
Position(* {{1}, {7}, {9}, {14}, {20}, {21}}*)
dauert ewig auf diesen potenziellen Wurzeln, oder zumindest länger als ich bereit war zu warten.]
Interessanterweise hängen diese zusätzlichen Wurzeln mit den Unterschieden zwischen den von NSolve
und Solve
:
Position, _?Positive](* {{1}, {2}, {3}, {14}, {21}, {22}, {23}, {24}}*)
Lassen Sie uns unsere neuen Wurzeln die folgenden sein und wir können sie unten überprüfen:
rootsEqNew = Pick];rootsEqNew // N(* {{ζ -> -24559.6 + 24559.6 I}, {ζ -> -3.78042 - 5.50655 I}, {ζ -> -3.20562 + 5.39914 I}, {ζ -> -0.0832786 - 722.827 I}, {ζ -> 6.98478 + 0.493405 I}, {ζ -> 722.642 - 0.100823 I}}*)
Checks
At sieht für die Neuzugänge zunächst nicht allzu gut aus:
eqExact /. rootsEqNew // N(* { 0. + 9.7614*10^12 I, (* {1} *) -1.49012*10^-8 + 3.91155*10^-8 I, (* {7} *) -1.39698*10^-8 - 3.63216*10^-8 I, (* {9} *) -2. + 1536. I, (* {14} *) 1.49012*10^-8 + 1.11759*10^-8 I, (* {20} *) 0. + 1024. I} (* {21} *)*)
Das Problem besteht darin, die Gleichung mit Maschinenpräzision zu bewerten.
N(* N::meprec warning about $MaxExtraPrecision being reached *)(* {0``69.62973568978663 + 0``69.69302870899077 I, 0``90.5174054423328 + 0``90.55817837498498 I, 0``90.50250822096415 + 0``90.54414468499085 I, 0``80.1824915073549 + 0``79.76650578675965 I, 0``90.47483650216002 + 0``90.49782363232914 I, 0``80.17292602755023 + 0``79.76710897249409 I}*)
Die Warnung scheint nicht signifikant zu sein. Das Anstoßen von $MaxExtraPrecision
auf 2000
erzeugt immer noch die Warnung und Nullen mit Genauigkeiten um 2020
bis 2040
. Wenn es sich um Nullen handelt, erzeugt N
wahrscheinlich immer die Warnung, da keine
Precision
(außer MachinePrecision
) haben kann.