C - Gleitkomma Genauigkeit
-
Hallo,
ich komme einfach nicht weiter.
Die Aufgabe ist
Eine andere Funktion benutzt ein Iterationsverfahren und liefert als double die positive
Quadratwurzel eines als Parameter zu übergebenden Radikanden mit der höchst möglichen
Genauigkeit zurück.
Beachten Sie die Ungenauigkeit reeller DatentypenNochmal meine Funktion
double quwl ( double rad )
{
auto double xN = 1 , xNplus1 = rad ;auto unsigned char i ; for ( i = 1 ; i < 10 ; i ++ ) { xN = xNplus1 ; xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; } return xNplus1 ;
}
Ich verstehe einfach nicht was die Aufgabe bzgl. der Genauigkeit will.
Einerseit habe ich beim Test von double Werten gemerkt, obwohl
eine Genauigkeit von 15 (signifkaten) Stellen für double angegeben ist.
Es durchaus Bsp. gibt in denen er mehr als 15 (signifkanten) Stellen unterscheiden kann.Andereseits wenn gesagt ist dass der double eine bestimmte höchste Genauigkeit (15 stellen) hat, dann rechnet das Programm doch selbst schon mit seiner höchsten Genauigkeit. Was gibt es da noch zu beachten?
Also ich sehe zwei Szenarien wenn man bspw.
1.
2.2 * 2.0 rechnet dann ist eig das genaueste Ergebnis das man angeben darf4.4000 (doppelt so viele Nachkommastellen)
Wenn man 4.4000000 angeben würde wäre das genauer als man das Ergebnis eig kennt
Ich denke aber nicht das die Aufgabe so gemeint ist und wüsste auch nicht wie ich das implementieren würde auf anhieb
- Wie oben schon gesagt
ich mache ja Berechnung mit xN in meiner Funktion und weise dann xNplus1
zu. Ich brauche doch eig nichtmal zu wissen wie die Genauigkeit ist.
wenn er bspw. xN * xN = 2.345 * 2.345 berechnet aber nicht genug stellen hätte um den genauen Wert weiterzugeben. Dann rundet er doch so gut er es eben selber weiß
ALso kommt am Ende doch das genaueste Ergebnis raus das man eben bekommen kann?
Hoffentlich kann jemand diesmal weiterhelfen.
Vielen Dank.
- Wie oben schon gesagt
-
@JamesNguyen
Untersuche doch mal deine Funktion.Baue mal eine kleine Testreihe auf. Du könntest beispielsweise 10 Millionen Zufallszahlen erzeugen und danach die Quadratwurzel mit deiner Funktion und mit sqrt() berechnen und dann miteinander vergleichen. Wie groß ist die größte Differenz?
Das Problem ist die numerische Stabilität. Gewisse Algorithmen reagieren empfindlich auf kleinere Änderungen, Rundungsfehler können sich hochschaukeln. Beispiel: Inverse eine Vandermonde Matrix, Addition (-> Kahan Summe)
-
(tut mir leid aber als anfänger kommt mir dein kurzer absatz der testreihe wie eine eigene Aufgabe vor...)
update:
double quwl ( double rad ) { if ( rad < 0 ) return - 1 ; auto double xN = 1 ; if ( xN > 1.7e154 && xN < 2.3E-154 && rad < 1.7e308 - xN * xN ) return - 1 ; auto double xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; while ( /*xNplus1 != xN &&*/ fabs ( xNplus1 - xN ) > rad * 1e-14 && xNplus1 > 2.3E-154 && xNplus1 < 1.7e154 && rad < 1.7e308 - xNplus1 * xNplus1 ) { xN = xNplus1 ; xNplus1 = 1 / ( 2 * xN ) * ( xN * xN + rad ) ; printf ( "%.20f\n" , xNplus1) ; } return xNplus1 ; }
so sieht die aktuelle version aus ich habe ein paar werte probiert und die werte stimmen eig
bloß das durchaus mal die hinterste stelle falsch ist
-
Ich hab jetzt mal das gemaht
for ( d = 0.1 ; d < 1000000 ; d *= 2.1 ) printf ( "%2u. %.18f\n" , k ++ , fabs ( sqrt ( d ) - quwl ( d ) ) ) ;
Ausgabe
- 0.000000000000000000
- 0.000000000000000056
- 0.000000000000000000
- 0.000000000000000111
- 0.000000000000000000
- 0.000000000000000444
- 0.000000000000000444
- 0.000000000000000000
- 0.000000000000000000
- 0.000000000000000000
- 0.000000000000000000
- 0.000000000000000000
- 0.000000000000003553
- 0.000000000000000000
- 0.000000000000007105
- 0.000000000000014211
- 0.000000000000000000
- 0.000000000000028422
- 0.000000000000000000
- 0.000000000000000000
- 0.000000000000113687
- 0.000000000000113687
was kann ich damit anfangen?
-
@JamesNguyen sagte in C - Gleitkomma Genauigkeit:
Also ich sehe zwei Szenarien wenn man bspw.
1.
2.2 * 2.0 rechnet dann ist eig das genaueste Ergebnis das man angeben darf
4.4000 (doppelt so viele Nachkommastellen)Wie kommst du darauf?
-
ich hätte gedacht das ist das normale vorgehen
wenn man zwei Werte multpliziert dann bekommt man die addierten nachkommstellen
also
2.00 * 2.000 = 2.00000
(das ist bei messungen auch so wenn du theoretisch zwei Messwerte exakt kennst 1.0 +-0 * 2.033 +- 0
dann ist dein bestwert 2.0330)
-
@JamesNguyen sagte in C - Gleitkomma Genauigkeit:
du theoretisch zwei Messwerte exakt kennst 1.0 +-0 * 2.033 +- 0
Das ist aber Computer Praxis und du hast nicht 2.033 sondern 2.03299999237060546875 (bei float)
-
@JamesNguyen sagte in C - Gleitkomma Genauigkeit:
das ist bei messungen auch so wenn du theoretisch zwei Messwerte exakt kennst 1.0 +-0 * 2.033 +- 0
dann ist dein bestwert 2.0330)Nein, das ist falsch. (bzw. deine Annahme +-0 stimmt bei Messwerten nie, man versteht unter 2.17 auch nicht, dass es 2.17000000000 bedeutet, sondern dass die Ungenauigkeit im Bereich der angegebenen Stellen liegt) Du musst Fehlerfortpflanzung rechnen. Nur weil du z. B. mit einem Wert von exakt 2.000000000000000... multiplizierst, hat dein Ergebnis danach nicht auf einmal so eine große Genauigkeit.