Mathematisch Runden ?



  • Was spricht gegen Franks Lösung?


  • Mod

    dEUs schrieb:

    Was spricht gegen Franks Lösung?

    pow ist langsam und ungenau.
    Zudem hätte er es mit einmal pow Aufruf und einer Division einfacher gehabt.



  • Hmm bin ich blind oder wo siehst du da bitte einen pow aufruf?


  • Mod

    Upps. Sorry. Ich habe mich versehen.

    Wenn es nur um die Ausgabe geht, ist dies genügend. Die anderen Lösungen waren zumindest flexibel genug um auf eine beliebige Anzahl von Stellen zu runden.

    Nein! Wenn es um eine schnelle Lösung geht, die eine Zahl einfach als Text gerundet ausgibt ist das natürlich am einfachsten.

    Ich halte jedoch einen Funktionsaufruf iw RoundFloat(x,2) für sprechender.



  • Abgesehen davon dass die printf() Lösung wohl die optimale ist... würde ich das wohl inetwa so machen:

    double RoundDecimal(double v, unsigned decimalPlaces)
    {
    	double scale = 1.0;
    	double accu = 10.0;
    	unsigned power = 1;
    
    	while (decimalPlaces > 0)
    	{
    		if (decimalPlaces >= power*2)
    		{
    			power *= 2;
    			accu *= accu;
    		}
    		else
    		{
    			scale *= accu;
    			decimalPlaces -= power;
    			accu = 10.0;
    			power = 1;
    		}
    	}
    
    	return floor(v * scale + 0.5) / scale;
    }
    

  • Mod

    @dEUs:

    Frank Erdorf schrieb:

    Text.Format("%.2lf",Zahl + 0.005);

    Jetzt muss ich mich korrigieren. Diese Lösung ist natürlich falsch! ⚠
    Weil printf und Format selbst natürlich runden.
    Manchmal sollte man sein Gehring einschalten bevor man antwortet!



  • Martin Richter schrieb:

    @Dravere: pow ist sehr ungenau und langsam:

    double RoundDouble(double dVal, int iPrec)
    {
    	// Need a default?
    	ASSERT(iPrec>=0);
    
    	// Shift
    	double 	dShift=1.0;
    	for (int i=0; i<iPrec; ++i)
    		dShift *= 10.0;
    
    	// multiply and split (get integral Part)
    	double	dResult, dFrac;
    	if (fabs(dFrac=modf(dVal*dShift,&dResult))>=0.5)
    		// Remove Fraction
    		dResult += dFrac<0.0 ? -1.0:1.0;
    
    	// Shift it back
    	return dResult/dShift;
    }
    

    Also ich bekomme mit deiner Funktion folgende Werte:

    double d=5.1234567890;  //echter Wert lt. Debugger: 5.1234567889999996
      double e;
    
      e=RoundDouble(d,10); //== 5.1234567889999996
      e=RoundDouble(d,9);  //== 5.1234567889999996
      e=RoundDouble(d,8);  //== 5.1234567899999996
      e=RoundDouble(d,7);  //== 5.1234567999999996
      e=RoundDouble(d,6);  //== 5.1234570000000001
      e=RoundDouble(d,5);  //== 5.1234599999999997
      e=RoundDouble(d,4);  //== 5.1234999999999999
      e=RoundDouble(d,3);  //== 5.1230000000000002
      e=RoundDouble(d,2);  //== 5.1200000000000001
      e=RoundDouble(d,1);  //== 5.0999999999999996
      e=RoundDouble(d,0);  //== 5.0000000000000000
    
      e=round(d,10);       //==-0.21474836480000001
      e=round(d,9);        //==-2.1474836480000001
      e=round(d,8);        //== 5.1234567900000005
      e=round(d,7);        //== 5.1234567999999996
      e=round(d,6);        //== 5.1234570000000001
      e=round(d,5);        //== 5.1234600000000006
      e=round(d,4);        //== 5.1234999999999999
      e=round(d,3);        //== 5.1230000000000002
      e=round(d,2);        //== 5.1200000000000001
      e=round(d,1);        //== 5.1000000000000005
      e=round(d,0);        //== 5.0000000000000000
    

    Ich habe die round() von Dravere mal mit einbezogen, die (zumindest bei einer Stellenanzahl <9) ähnlich präsize ist. Genauer kriegt man es mit C++ nicht hin?



  • Gabs da mal nicht Funktionen wie "floor()" oder "ceil()" ? Waren die nicht zum auf und abrunden da?



  • Uruk-h4j schrieb:

    Gabs da mal nicht Funktionen wie "floor()" oder "ceil()" ? Waren die nicht zum auf und abrunden da?

    die kann man aber imho nur für das Runden auf Ganzzahlen benutzen.



  • @matze: Das Problem ist nicht C++, sondern FPU-Rechengenauigkeit sowie die interne Darstellung von Gleitkomma-Zahlen. Rationale Zahlen mit einer endlichen Darstellung bzgl. Basis 10 sind periodisch unendlich bzgl. Basis 2.

    Damit ist "Runden durch Rechnen" problematisch, ein endgültiges Runden muß bei der Umwandlung in Text erfolgen.
    ----
    @Martin Richter:
    So einen Gehring hätt' ich auch gern, gibt es den auch mit akku/solar-betrieb? 🙄
    ----

    Genauer geht es natürlich mit einer eigenen Langzahl-Arithmetik, siehe Windows' calc.exe


Anmelden zum Antworten