Python-Berechnungsfehler

8

Ich verwende die API mpmath, um die folgende Summe zu berechnen

Betrachten wir die Serie u0, u1, u2, definiert durch:

%Vor%

Die Serie konvergiert auf 2, aber mit dem Rundungsproblem scheint sie auf 2000 zu konvergieren.

%Vor%

Mein Code:

%Vor%

meine schlechten Ergebnisse:

%Vor%

Ich habe versucht, mit einigen anderen Funktionen (fdiv ...) oder um die Genauigkeit zu ändern: dasselbe schlechte Ergebnis

Was ist falsch an diesem Code?

Frage: Wie ändere ich meinen Code, um den Wert 2.0 zu finden ??? mit der Formel:

un + 1 = 2003 - 6002 / un + 4000 / un un-1

Danke

    
aspire99 02.01.2012, 09:00
quelle

6 Antworten

13

Mit dem Dezimal-Modul können Sie sehen, dass die Reihe auch eine Lösung hat, die bei 2000 konvergiert:

%Vor%

Die Rekursionsbeziehung hat mehrere feste Punkte (eins bei 2 und das andere bei 2000):

%Vor%

Die Lösung bei 2 ist ein instabiler Fixpunkt. Der attraktive Fixpunkt liegt bei 2000.

Die Konvergenz kommt sehr nahe an zwei und wenn die Rundung bewirkt, dass der Wert etwas über zwei hinausgeht, wird dieser Unterschied immer wieder verstärkt, bis er 2000 trifft.

    
Raymond Hettinger 02.01.2012 09:11
quelle
3

Ihre (nicht lineare) Wiederholungssequenz hat drei Fixpunkte: 1 , 2 und 2000 . Die Werte 1 und 2 sind im Vergleich zu 2000 nahe beieinander, was normalerweise ein Hinweis auf instabile Fixpunkte ist, weil sie "fast" Doppelwurzeln sind.

Sie müssen etwas Mathe machen, um weniger früh auseinander zu gehen. Sei v(n) eine Seitensequenz:

%Vor%

Folgendes gilt:

%Vor%

Sie können dann einfach v(n) berechnen und u(n) von u(n) = v(n)/(1+2^n) ableiten:

%Vor%

Und das Ergebnis:

%Vor%

Beachten Sie, dass später noch voneinander abweichen wird Um wirklich zu konvergieren, müssen Sie v(n) mit beliebiger Genauigkeit berechnen. Aber das ist jetzt viel einfacher, da alle Werte Ganzzahlen sind.

    
sam hocevar 02.01.2012 18:31
quelle
2

Sie berechnen Ihre Anfangswerte mit einer Genauigkeit von 53 Bits und weisen diesen gerundeten Wert der hochpräzisen mpf-Variablen zu. Sie sollten u0 = mpf (3) / mpf (2) und u1 = mpf (5) / mpf (3) verwenden. Sie bleiben für ein paar mehr Interaktionen nahe bei 2, aber Sie werden trotzdem bei 2000 konvergieren. Dies liegt an einem Rundungsfehler. Eine Alternative besteht darin, mit Brüchen zu rechnen. Ich habe gmpy verwendet und der folgende Code konvergiert zu 2.

%Vor%     
casevh 02.01.2012 10:01
quelle
2

Wenn Sie mit unendlicher Genauigkeit rechnen, erhalten Sie 2 , ansonsten erhalten Sie 2000 :

%Vor%

Ausgabe

%Vor%     
jfs 02.01.2012 10:25
quelle
1

Nun, wie casevh sagte, habe ich gerade die mpf-Funktion in die ersten Initialbegriffe in meinem Code eingefügt:

u0 = mpf (3) / mpf (2)

u1 = mpf (5) / mpf (3)

und der Wert konvergieren für 16 Schritte auf den korrekten Wert 2.0, bevor sie erneut divergieren (siehe unten).

Also, selbst mit einer guten Python-Bibliothek für Gleitkommaarithmetik mit beliebiger Genauigkeit und einigen grundlegenden Operationen kann das Ergebnis völlig falsch werden und es ist kein algorithmisches, mathematisches oder Wiederholungsproblem, wie ich manchmal lese.

Also ist es notwendig wachsam und kritisch zu bleiben !!! (Ich habe große Angst vor der Funktion mpmath.lerchphi (z, s, a); -)

  

2 1.8000000000000000000000000000000000000000000000022 3   1,8888888888888888888888888888888888888888888913205 4 1,9411764705882352941176470588235294117647084569125 5 1,9696969696969696969696969696969696969723495083846 6 1,9846153846153846153846153846153846180779422496889 7 1,992248062015503875968992248062018218070968279944 8 1,9961089494163424124513618677070049064461141667961 9 1,998050682261208576998050684991268132991329645551 10 1,9990243902439024390243929766241359876402781522945 11 1,9995119570522205954151303455889283862002420414092 12 1,9997559189650964147435086295745928366095548127257 13 1,9998779445868451615169464386495752584786229236677 14 1,9999389685715481608370784691478769380770569091713 15 1,9999694860884747554701272066241108169217231319376 16 1,9999874767910784720428384947047783821702386000249 17 2,0027277350948824117795762659330557916802871427763 18 4,7316350177463946015607576536159982430500337286276 19 1156,6278675611076227796014310764287933259776352198 20 1998,5416721291457644804673979070312813731252347786 21 1999,9985406086893 66669273522363692463645090555294 22 1999.9999985406079725746311606572627439743947878652

    
aspire99 03.01.2012 07:21
quelle
1

Die genaue Lösung für Ihre Rekursionsbeziehung (mit den Anfangswerten u_0 = 3/2, u_1 = 5/3) wird leicht als

bestätigt %Vor%

Das Problem, das Sie sehen, ist, obwohl die Lösung so ist, dass

%Vor%

Dieses Limit ist ein abstossender Fixpunkt Ihrer Rekursionsbeziehung. Das heißt, any Abweichung von den korrekten Werten von u_ {n-1}, u {n-2} für einige n führt zu weiteren Werten, die von der korrekten Grenze abweichen. Folglich, wenn Ihre Implementierung der Rekursionsbeziehung nicht korrekt alle u_n-Werte genau darstellt, kann erwartet werden, dass sie eine Abweichung von der korrekten Grenze aufweisen und zu dem falschen Wert von 2000 konvergieren, der zufälligerweise der einzige ist anziehender Fixpunkt Ihrer Rekursionsbeziehung.

(*) Tatsächlich ist u_n = (2 ^ (n + 1) + 1) / (2 ^ n + 1) die Lösung für jedes Rekursionsverhältnis der Form %Vor%

mit den gleichen Anfangswerten wie oben angegeben, wobei C eine willkürliche Konstante ist. Wenn ich keinen Fehler gemacht habe, die Wurzeln des charakteristischen Polynoms zu finden, wird dies die Menge der Fixpunkte {1, 2, C - 3} \ {0} haben. Die Grenze 2 kann entweder ein abstoßender fester Punkt oder ein anziehender fester Punkt sein, abhängig von dem Wert von CEg, für C = 2003 ist der Satz fester Punkte {1, 2, 2000}, wobei 2 ein Repeller ist, wohingegen für C = 3 sind die Fixpunkte {1, 2}, wobei 2 ein Attraktor ist.

    
r.e.s. 05.01.2012 05:30
quelle