C - Gleitkomma Genauigkeit 2



  • 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



  • 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 ) = 1

    er 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.41421356237309490000

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

Anmelden zum Antworten