C - Gleitkomma Genauigkeit 2
-
@JamesNguyen Je mehr Berechnungen du machst, umso größer kann sich der Fehler fortpflanzen, d.h. die Ungenauigkeit steigt.
-
ah meinst du also dass ich diese ungenauigkeiten gar nicht verhindern kann
sondern mein ergebnis nicht beliebig genau angeben kann?
wenn das so ist. wie weiß ich wie groß die ungenauigkeit ist
und wie kann ich mein ergebnis darauf anpassen?
-
@JamesNguyen sagte in C - Gleitkomma Genauigkeit 2:
wie weiß ich wie groß die ungenauigkeit ist
und wie kann ich mein ergebnis darauf anpassen?Abschätzen.
Das hängt von deinem speziellen Problem ab.
-
@DirkB sagte in C - Gleitkomma Genauigkeit 2:
Das fabs ( xNplus1 - xN ) > rad * 1e-14 ist die eigentliche Bedingung.
Mit dem 1E-14 legst du die Genauigkeit fest.du hast ja geschrieben das legt die genauigkeit fest.
Ich würde eher sagen, dass legt fest ob er mehr oder weniger stellen des ergebnisses zurückgibt
Wie ungenau mein Ergebnis durch sich vergrößernde Fehler ist , ist damit nicht gesagt.
-
Überprüfe mal die Zeile 7 (
if
-Bedingung) - die kann so niemals zutreffen.Und den
!=
-Vergleich in derwhile
-Bedingung kannst du auch weglassen, da du doch sowieso die Differenz überprüfst.
Auch den Sinn des letzten Vergleichs in der Bedingung verstehe ich nicht.PS: Für die Literale solltest du besser Konstanten (Makros) benutzen, damit der Code lesbarer wird.
-
ok update mit makros
double quwl ( double rad ) { if ( rad < 0 ) return - 1 ; auto double xN = 1 ; if ( xN < sqrt ( DBL_MIN ) || xN > sqrt ( DBL_MAX ) || rad > DBL_MAX - xN * xN ) return - 1 ; auto double xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; while ( fabs ( xNplus1 - xN ) > rad * 1e-14 && xNplus1 > sqrt ( DBL_MIN ) - 1 && xNplus1 < sqrt ( DBL_MAX ) + 1 && rad < DBL_MAX - xNplus1 * xNplus1 + 1 ) { xN = xNplus1 ; xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; } return xNplus1 ; }
-
du hast vorher mal gesagt ich habe epsilon entdeckt
ich habe das mit probieren sehr weniger werte gefunden
werte die allein bei der != bedingung die iteration nicht abgebrochen haben
und so das programm ewig weiter lief
ist das eig das richtige epsilon?
wenn ja wieso?
lässt sich das mit der genauigkeit von double begründen?
-
Der Wert 0
liefert
-1.#IND00
?
-
@JamesNguyen sagte in C - Gleitkomma Genauigkeit 2:
du hast vorher mal gesagt ich habe epsilon entdeckt
Epsilon ist die Bezeichnung für die Genauigkeit.
Es ist die Differenz, unterhalb der zwei Werte als gleich gelten.Es ging auch nicht um einen speziellen Wert, sondern um die Tatsache dass man den braucht.
-
heißt das ich kann den selbst festlegen und es gibt keinen richtigen und falschen?
naja es könnte bspw. sein
das ich zu einem wert
ein epsilon finde
das genau dort die wurzeliteration beendet sodass die letzte stelle korrekt ist
aber gibt es ein bestimmtes epsilon das dies für alle werte richtig macht?
Oder soll ich dafür eine möglichst großes wählen?
-
@JamesNguyen Epsilon ist ein Wert, kein Faktor.
Aber du kannst Epsilon aus den Vergleichswerten und der Genauigkeit berechnen.
Als Faktor hattest du ja 1e-14 genommen.
-
weil wenn ich das epsilon bei
radikant * 1e^-14
lasse
habe ich bspw. (bei vergleich mit wolfram alpha)
für bspw.
quwl ( 0.123456789012345 )
ist die letzte stelle von mir nicht richtig gerundet
-
Dieser Beitrag wurde gelöscht!
-
@DirkB sagte in C - Gleitkomma Genauigkeit 2:
@JamesNguyen Epsilon ist ein Wert, kein Faktor.
Aber du kannst Epsilon aus den Vergleichswerten und der Genauigkeit berechnen.
Als Faktor hattest du ja 1e-14 genommen.wie kann ich das machen?
welche vergleichswerte meinst du?
weil diesen faktor habe ich glaube lediglich aus der wurzel (0.0025) glaube ich weil da die schleife endlos war
dann habe ich den solange größer gemacht bis die scfhleife abgebrochen hat
-
Ich habe jetzt mal weiter dran gearbeitet
double quwl ( double rad ) { if ( rad < 0 ) return - 1 ; auto double xN = 1 ; if ( xN < sqrt ( DBL_MIN ) || xN > sqrt ( DBL_MAX ) || rad > DBL_MAX - xN * xN ) return - 1 ; auto double xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; while ( fabs ( xNplus1 - sqrt ( rad ) ) < fabs ( xN - sqrt ( rad ) ) && xNplus1 >= sqrt ( DBL_MIN ) && xNplus1 <= sqrt ( DBL_MAX ) && rad <= DBL_MAX - xNplus1 * xNplus1 ) { xN = xNplus1 ; xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; } return xN ; }
gebe also xN und nicht xNplus1 zurück
zu Bedingung
angenommen
ich iteriere also
und
es kommt soll 5 am ende rauskommen
dann itereriert er
24 -> 15 -> 9 -> 6 -> 4
und dann bricht er ab (hier wird die annahme getroffen der wert kann auch 'auf die andere seite von 5 das wäre also nicht mehr streng monoton)
so
jetzt also betrag ( 6 - 5 ) = 1
betrag ( 4 -5 ) = 1er bricht also ab
in meinem programm
würde er die 6 also xN
zurückgeben
und nicht 4 was xNplus1.
welche der beiden werte ist der richtige?
bzw. allgemeiner ist der wert richtiger dessen letzte nachkommastelle mit der richtigen zahl übereinstimmt oder
der wert dessen letzte nachkommastelle(n) vlt nicht übereinstimmen aber der wert liegt näher am richtigen wert?wenn ich nun xNplus1 ausgebe
also
den letzten wert von
1.41421356237309510000
1.41421356237309490000web2.0 rechnre liefert
1.414213562373095
hier wären beide werte gleich gut aber man würde sehen dass der die iteration von oben den richtigen wert unterschreitet hat
wolfram alpha liefert
1.41421356237309504....
hier wäre also der obere wert richtiger
könnte man das allgemein sagen und ich nehme lieber
xN also den oberen werte
und macht dann < statt <= in der bedingung?
-
ok also ich habe mir gedacht
ich hab ja die bedingung mit <
dass heißt er hört auf
sobald der der abstand zum richtigen wert > oder = ist
ich würde sagen
in beiden fällen (> offensichtlich) ist falls der richtige wert sogar weitere nachkommstellen
dem xN näher als dem xNplus1
also xN der allgemein richtigere wert.
falls der richtige wert keine weiter nachkommastellen hat
ist bei gleichheit
xN und xNplus1 gleich gut
ne das ist alles falsch
wenn ich mich von unten dem richtigen wert nähere
dann ist xNplus1 der bessere Wert
wie kann ich also entscheiden?
-
irgendwie sind meine ergebnisse schlechter geworden
seit ich für den start wert
auto double xN = rad > 2 ? log ( rad ) / log ( 2 ) : rad > 0.5 ? rad / 2 : rad > - 1 ? rad * 2 : - 1 ;
gemacht habe..
-
Meine aktuelle Version
aber die Startwerte von mir liefern immer noch schlechtere Ergebenisse als x0 = 1
double quwl ( double rad ) { if ( rad < 0 ) return - 1 ; auto double xN = rad > 2 ? log ( rad ) / log ( 2 ) : rad > 0.5 ? rad / 2 : rad > - 1 ? rad * 2 : - 1 ; if ( xN < sqrt ( DBL_MIN ) || xN > sqrt ( DBL_MAX ) || rad > DBL_MAX - xN * xN ) return - 1 ; auto double xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; while ( xNplus1 >= sqrt ( DBL_MIN ) && xNplus1 <= sqrt ( DBL_MAX ) && rad <= DBL_MAX - xNplus1 * xNplus1 ) { if ( fabs ( xNplus1 - sqrt ( rad ) ) > fabs ( xN - sqrt ( rad ) ) ) return xN ; if ( fabs ( xNplus1 - sqrt ( rad ) ) == fabs ( xN - sqrt ( rad ) ) ) return xNplus1 > xN ? xNplus1 : xN ; xN = xNplus1 ; xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; } return xNplus1 ; }