cos/sin berechnungsgeschwindigkeit?



  • hallo,
    also ich wollte mal kurz wissen welche der beiden varianten zur cos/sin berechnung schneller ist?

    cos(α) und sin(α) mit
    α = 2*atan(f/g) für g≠0
    α = π für g=0

    oder 2)
    cos(α) = (g2 - f2)/(g2 + f2)
    sin(α) = 2*f*g/(g2 + f2)

    wobei f und g float-werte sind nicht beide gleichzeitig 0 werden.
    der hintergrund ist das ich sehr viele cosinus und sinus werte ausrechnen muss und daher gerne die schnellere verwenden möchte.
    vielen dank schonmal im voraus.



  • schreib dir ein testprogramm und stopp die zeit, z.b. mit der funktion clock()
    mfg



  • Ich denke, dass die zweite Variante um einiges schneller sein dürfte, da die mathematischen Funktionen wie atan sich erfahrungsgemäß relativ viel Zeit bei der Berechnung lassen.



  • Nanyuki schrieb:

    Ich denke, dass die zweite Variante um einiges schneller sein dürfte, da die mathematischen Funktionen wie atan sich erfahrungsgemäß relativ viel Zeit bei der Berechnung lassen.

    Erfahrungsgemäß?
    Meines Wissens sind die meisten dieser Funktionen über Wertetabellen implementiert...



  • Du kannst auch eine eigene schnellere Funktion schreiben.
    Ich hab mal vor einer Weile das hier geschrieben:

    float SinFast(const float f)
    {
    	float fTemp_3=f*f*f;
    	return( f>PI
    			? SinFast(f-2.F*PI)
    			: f<-PI
    			  ? SinFast(f+2.F*PI)
    			  : (f - 0.0001984126984F * fTemp_3 * fTemp_3 * f           // f^7/7! +f (f^1/1!=f)
    			       + 0.0083333333333F * fTemp_3 * f * f                 // f^5/5!
    				   - 0.1666666666667F * fTemp_3  ));                    // f^3/3!
    }
    float CosFast(float f)
    {	return( SinFast(f+.5F*PI) );}
    

    ist schneller, aber ab manchmal etwas ungenau. 😉



  • an die wertetabellen hatte ich auch schon gedacht, allerdings weiß ich halt nicht genau, ob das immer noch schneller ist als die paar operation auszuführen und genau das ist frage. da bei beiden eine division ausgeführt werden muss kann man diese operation bei der betrachtugn weglassen.



  • .filmor schrieb:

    Erfahrungsgemäß?
    Meines Wissens sind die meisten dieser Funktionen über Wertetabellen implementiert...

    Die Implementierungsdetails kenne ich nicht... aber im Vergleich zu Divisionen und erst recht zu Multiplikationen haben diese Funktionen eine weitaus höhere Laufzeit. Deswegen vermute ich, dass die zweite Variante schneller sein dürfte (wenn beide wirklich gleichwertig sind).
    Aber naja, im Zweifelsfall einfach nachmessen... das ist wohl der bessere Weg, anstatt sich auf irgendwelche Ratschläge zu verlassen.



  • noch mehr ungenauigkeit, als numerisch sowieso schon gegeben ist, kann ich mir leider nicht leisten.



  • Edit: war wohl (teilweise) Unsinn.



  • also ich hab mir mal kurz folgenden code geschrieben. für die klasse cclock mag jeder seine eigene zeitmessung einfügen.

    cclock clk;
    	const float d = 1000.0f;
    	const float step = 0.5f;
    	float f;
    	float g;
    	float ff;
    	float gg;
    	float abs;
    	float a;
    	float c;
    	float s;
    	int i = 5;
    	while(i--)
    	{
    		clk.set_start_time();
    		for(f = -d; f <= d; f += step)
    			for(g = -d; g <= d; g += step)
    				if(f != 0 || g != 0)
    				{
    					ff = f*f;
    					gg = g*g;
    					abs = 1 / (ff + gg);
    					c = (gg - ff) * abs;
    					s = 2.0f * f * g * abs;
    				};
    		clk.set_finish_time();
    		std::cout << "Zeitmessung ohne Cos(), Sin()" << clk << std::endl;
    
    		clk.set_start_time();
    		for(f = -d; f <= d; f += step)
    			for(g = -d; g <= d; g += step)
    			{
    				if(g == 0)
    				{
    					c = -1;
    					s = 0;
    				}
    				else
    				{
    					a = 2 * atan(f/g);
    					c = cos(a);
    					s = sin(a);
    				};
    			};
    		clk.set_finish_time();
    		std::cout << "Zeitmessung mit Cos(), Sin()" << clk << std::endl;
    	}
    
    Zeitmessung ohne Cos(), Sin()t = 0.359s
    Zeitmessung mit Cos(), Sin()t = 9.297s
    Zeitmessung ohne Cos(), Sin()t = 0.36s
    Zeitmessung mit Cos(), Sin()t = 9.36s
    Zeitmessung ohne Cos(), Sin()t = 0.375s
    Zeitmessung mit Cos(), Sin()t = 9.282s
    Zeitmessung ohne Cos(), Sin()t = 0.328s
    Zeitmessung mit Cos(), Sin()t = 9.36s
    Zeitmessung ohne Cos(), Sin()t = 0.36s
    Zeitmessung mit Cos(), Sin()t = 9.328s
    

    resultat ist das cos(),sin(),atan() berechnung ca. um den faktor 30 langsamer war als die andere methode, damit dürfte der gewinner feststehen 😉



  • Ich habe auch mal eine Sinusfunktion selbst geschrieben. ( Ich lerne noch ).

    double sinius(double x)
    {
    double Sinus;             
    double xquadrat, x_hoch_3, x_hoch_5, x_hoch_7, x_hoch_9, x_hoch_11, x_hoch_13;
    //double x_hoch_15;
    double PI = 3.141592653589793;
    double ZweiPI = 6.283185307179586;
    double PIhalbe = 1.570796326794897;
    
    	while (x < 0) x = x + ZweiPI;    //Jetzt ist x auf jeden Fall > 0
    	while (x > ZweiPI) x = x - ZweiPI; //Jetzt liegt x im Intervall [0..ZweiPI]
    	if (x > PI) x = x - ZweiPI;       //Jetzt liegt x im Intervall [-PI..PI]
    	if (x > PIhalbe) x = PI - x;    //Jetzt liegt x im Intervall [-PI..PIhalbe]
    	if (x < -PIhalbe) x = -x - PI; //Jetzt liegt x im Intervall [-PIhalbe..PIhalbe]
    
    	xquadrat = x * x;                 
    	x_hoch_3 = x * xquadrat;          
    	x_hoch_5 = x_hoch_3 * xquadrat;   
    	x_hoch_7 = x_hoch_5 * xquadrat; 
    	x_hoch_9 = x_hoch_7 * xquadrat;   
    	x_hoch_11 = x_hoch_9 * xquadrat;   
    	x_hoch_13 = x_hoch_11 * xquadrat;  
    //	x_hoch_15 = x_hoch_13 * xquadrat;  
    
    	return x - x_hoch_3/6 + x_hoch_5/120 - x_hoch_7/5040 + x_hoch_9/362880
    	        - x_hoch_11/39916800 + x_hoch_13/6227020800.0 
    	       /* - x_hoch_15/1307674368000.0 */  ;
    

    Ich hoffe, es rechnet richtig.

    Etwa 100000 Berechnungen werden durchgeführt, noch bevor man mit den Wimpern zucken kann. Erst ab einer Million Berechnungen muß man einen kleinen Augenblick warten. Die normale Sinusfunktin sin() aus <math.h> ist allerdings noch einmal etwa doppelt so schnell. Es müssen wohl sehr viele Berechnungen sein, die FreakyBKA da durchführen will.


Log in to reply