Problem mit quadratwurzel ?



  • Also ich hab folgendes Programm geschrieben ➡

    #include <iostream>
    #include <conio.h>
    #include <iomanip>
    
    using namespace std;
    
    double quadratwurzel(double a);
    
    void main()
    {
    	double zahl;
    
    	cout << fixed << setprecision(15);
    
    	cout << "\t\tBerechnung der Quadratwurzel!\n";
    	cout << "\n\tBitte geben Sie eine Zahl ein!\n";
    	cout << "Zahl: "; cin >> zahl;
    	cout << "\n\tDie Zugeh\x94rige Quadratwurzel = "
    		 << quadratwurzel(zahl);
    	getch();
    }
    
    double quadratwurzel(double a)
    {
    	double wurzel = 0.0;
    
    	while(wurzel*wurzel < a)
    	{
    		wurzel += 0.01;
    	}
    
    	return (wurzel);
    }
    

    Mein Problem zeigt sich beim Ausführen der EXE-Datei,
    wenn man da Beispielsweise als Zahl die 9 eingibt,
    müsste,

    da immer in 0.01er-schritten erhöht wird, normalerweise bei einer precision von 15 genau 3.00000000000000
    angezeigt werden.
    🙄

    Angezeigt wird aber 3.00999999999998! ⚠

    Woran könnte das liegen warum Rundet der so 😕



  • Es wird nicht in 0.01-Schritten erhöht, weil 0.01 keine Zahl ist, die als float oder double exakt darstellbar ist. Du machst also bei jedem Schritt einen Fehler, und der addiert sich auf.

    Du kannst ja mal 0.0078125 als Schrittweite ausprobieren.



  • aba warum dann 0.0078125 😕



  • 0.0078125 ist 1/128. Diese Zahl ist als float/double ohne Fehler darstellbar, weil sie ein abbrechender "Dual"-Bruch ist.

    Genau wie du 1/3 nicht als Dezimalbruch exakt darstellen kannst, kannst du 1/100 nicht als Dualbruch darstellen, ohne Stellen abzuschneiden.



  • Ich hab mal ne wurzel Funktion geschieben die berechnet den Wert um einiges schneller

    double wurzel (double radikant, double wurzelexponent = 2){                     //     1/n                 
    double xA,xZ=1;                                                                 //x = x                    
    double xAVergleich,xZVergleich;                                                 //     0                   
    bool done = false;                                                              ///////////////////////////////
    bool ersterDurchlauf = false;                                                   //      n - 1         x    
    int probe_wurzelexponent = wurzelexponent;                                      //                     0   
                                                                                    //x   = ----- * x  + ----- 
                                                                                    // i+1           i      n-1
            if (!((radikant < 0) && (probe_wurzelexponent%2==0))){                  //        n          n*x   
                    while (!done){                                                  //                      i  
                         xA = (((wurzelexponent-1)/wurzelexponent)*xZ)+(radikant/(wurzelexponent*potenz(xZ,wurzelexponent-1)));
    
                            if (xA < 0)xAVergleich = xA*(-1);else xAVergleich = xA;//BETRAG
                            if (xZ < 0)xZVergleich = xZ*(-1);else xZVergleich = xZ;//BETRAG
    
                            if (ersterDurchlauf == true)if (xZVergleich - xAVergleich < 0.00000001)done = true;
                            ersterDurchlauf = true;
    
                            xZ = xA;
                     }
            }
            else xA = 0;
            return xA;
    }
    


  • SYE schrieb:

    Ich hab mal ne wurzel Funktion geschieben die berechnet den Wert um einiges schneller
    ...

    das allgemeinmachen hat vieles verschlimmert, gell?
    was sagen die namen xA und xZ aus?
    warum alle variablen so früh definiert?

    lieber tiefe sparen, also statt

    if (!((radikant < 0) && (probe_wurzelexponent%2==0))){                  //        n          n*x    
       while (!done)
          ...
    }
    else xA = 0; 
    return xA;
    

    lieber

    if (((radikant < 0) && (probe_wurzelexponent%2==0)))
       return 0;
    while (!done)
       ...
    return xA;
    

    merke: sofort raus aus der funktion, sobald das ergebnis feststeht.

    abs() benutzen wäre feiner.

    bildet

    if (ersterDurchlauf == true)if (xZVergleich - xAVergleich < 0.00000001)done = true;
    

    nur ne do-schleife nach?

    deine formel kenne ich gar nicht. unter welchem namen ist sie in google zu finden?



  • keine Ahnung wo die Formel unter google zu finden ist hab sie aus einem Mathebuch


Anmelden zum Antworten