Wenn Sie nach einer guten Grenze für Ihren Rundungsfehler suchen, benötigen Sie nicht unbedingt eine Bibliothek mit beliebiger Genauigkeit. Sie können stattdessen die laufende Fehleranalyse verwenden.
Ich konnte keine gute Online-Referenz finden, aber alles ist in Abschnitt 3.3 von Nick Highams Buch "Genauigkeit und Stabilität numerischer Algorithmen" beschrieben. Die Idee ist ganz einfach:
- Berechnen Sie Ihren Code neu, sodass Sie in jeder Zeile eine einzelne Zuordnung einer einzelnen arithmetischen Operation haben.
xErstellen Sie z. B. für jede Variable eine Variable, x_errdie auf Null initialisiert wird, wenn xeine Konstante zugewiesen wird.
z = x * yAktualisieren Sie für jede Operation z. B. die Variable z_errmit dem Standardmodell der Gleitkomma-Arithmetik und den daraus resultierenden zund den ausgeführten Fehlern x_errund y_err.
- Dem Rückgabewert Ihrer Funktion sollte dann auch ein entsprechender
_errWert zugeordnet sein. Dies ist eine datenabhängige Grenze Ihres gesamten Rundungsfehlers.
Der knifflige Teil ist Schritt 3. Für die einfachsten Rechenoperationen können Sie die folgenden Regeln verwenden:
z = x + y -> z_err = u*abs(z) + x_err + y_err
z = x - y -> z_err = u*abs(z) + x_err + y_err
z = x * y -> z_err = u*abs(z) + x_err*abs(y) + y_err*abs(x)
z = x / y -> z_err = u*abs(z) + (x_err*abs(y) + y_err*abs(x))/y^2
z = sqrt(x) -> z_err = u*abs(z) + x_err/(2*abs(z))
wo u = eps/2ist die gerundete Einheit. Ja, die Regeln für +und -sind gleich. op(x)Mit der Taylor-Reihen-Erweiterung des Ergebnisses, auf das angewendet wird, können Regeln für jede andere Operation einfach extrahiert werden op(x + x_err). Oder Sie können versuchen, zu googeln. Oder mit Nick Highams Buch.
Betrachten Sie als Beispiel den folgenden Matlab / Octave-Code, der Polynome in den Koeffizienten aan einem Punkt unter xVerwendung des Horner-Schemas auswertet :
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
s = a(k) + x*s;
end
Für den ersten Schritt teilen wir die beiden Operationen in s = a(k) + x*s:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
z = x*s;
s = a(k) + z;
end
Wir führen dann die _errVariablen ein. Beachten Sie, dass die Eingaben aund xals genau angenommen werden, aber wir könnten genauso gut auch den Benutzer auffordern, entsprechende Werte für a_errund zu übergeben x_err:
function [ s , s_err ] = horner ( a , x )
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = ...;
s = a(k) + z;
s_err = ...;
end
Schließlich wenden wir die oben beschriebenen Regeln an, um die Fehlerausdrücke zu erhalten:
function [ s , s_err ] = horner ( a , x )
u = eps/2;
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = u*abs(z) + s_err*abs(x);
s = a(k) + z;
s_err = u*abs(s) + z_err;
end
Beachten Sie, dass die entsprechenden Ausdrücke in den Fehlerausdrücken einfach ignoriert werden , da wir keine haben a_erroder x_errz. B. angenommen werden, dass sie Null sind.
Et voilà! Wir haben jetzt ein Horner-Schema, das eine datenabhängige Fehlerschätzung (Anmerkung: Dies ist eine Obergrenze für den Fehler) neben dem Ergebnis zurückgibt .
Als Randnotiz: Da Sie C ++ verwenden, können Sie eine eigene Klasse für Gleitkommawerte erstellen, die den _errTerm enthält, und alle arithmetischen Operationen überladen, um diese Werte wie oben beschrieben zu aktualisieren. Bei großen Codes kann dies die einfachere, wenn auch rechnerisch weniger effiziente Route sein. Allerdings können Sie eine solche Klasse möglicherweise online finden. Eine schnelle Google-Suche gab mir diesen Link .
± ux ( 1 ± u )