C - Gleitkomma Genauigkeit 2



  • Hallo nochmal,

    ok ich habe glaube ich die ganze Zeit Blödsinn erzählt
    Hier jetzt meine neue Funktion für Quadratwurzel

    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 ;
    }
    

    Ich kenne das Problem bspw. wenn ein System nur 6 sign stellen unterscheiden könnte

    dann wären 1234.2399 = 1234.23 gleich

    *heißt das hier eig dass der COmpiler die Zahl links beim vergleich nicht auf 1234.24 aufrundet sonder einfach hinter der 6. stelle abschneidet?

    Jedenfalls gibt es bzgl dieses WIssens Probleme mit der FUnktion?
    Ich sehe gerade keine

    Danke,
    James



  • ok ich habe gemerkt bei quwl( 3 ) beendet das Programm nicht ich glaube mal die xN gleichen sich hier nie..

    Wie kann das beheben?



  • 1.75000000000000000000
    1.73214285714285700000
    1.73205081001472760000
    1.73205080756887740000
    1.73205080756887720000
    1.73205080756887760000
    1.73205080756887740000
    1.73205080756887720000
    1.73205080756887760000
    1.73205080756887740000
    1.73205080756887720000
    1.73205080756887760000
    1.73205080756887740000
    1.73205080756887720000
    1.73205080756887760000
    1.73205080756887740000
    1.73205080756887720000
    1.73205080756887760000
    1.73205080756887740000



  • Ich habe nun meine FUnktion angepasst und sie bricht jetzt auch immer ab denke ich

    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 ;
    }
    

    aber kann mir jemand insbesondere in Verbindung mit der Genauigkeit von double erklären warum es funktioniert?

    Auch habe ich gemerkt das ich die erste Bedingung in der while-Bedingung nicht unbedingt brauche

    xNplus1 != xN && fabs ( xNplus1 - xN ) > rad * 1e-14 &&

    also die Gleichheit. warum?

    Danke,
    James



  • @JamesNguyen Du wurdest schon gebeten, deinen Code in Codetags zu packen.

    Markiere deine Funktion mit der Maus und clicke au das </> neben dem C++ in der Editleiste.

    Du hast Epsilon entdeckt.



  • Also so wie ich das sehe habe ich keine Ahnung wie ich Rundungsfehler in meinem Programm berücksichtige. einfach keine Ahnung



  • @JamesNguyen Das fabs ( xNplus1 - xN ) > rad * 1e-14 ist die eigentliche Bedingung.

    Mit dem 1E-14 legst du die Genauigkeit fest.



  • ok , ist das dann die richtige Bedingung für diese Problem ?

    und sind die restlichen Bedingungen in meinem While ausdruck auch sinnvoll oder notwendig?

    aber was ich eben noch nicht versteh ist ob ich Probleme

    von der Natur

    0.1 + 0.1 +0.1 + usw.

    in meinem Programm berücksichtigt habe

    da in meinem programm ja auch mit doubles gerechnet wird

    bspw. xN * xN



  • @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 der while-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 ;
    }
    


  • @DirkB

    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


Anmelden zum Antworten