Template zum potenzieren
-
Pellaeon schrieb:
...es funzt wunderbar...

Super !Schönen Tag noch,
Simon2.
-
Simon2 schrieb:
Allerdings muss ich gestehen, dass ich nicht genau weiß, ws Du mit "Membertemplate" meinst....
Gruß,
Simon2.
Damit meinte ich Methode von Klassen.
Das mit den Funktionstemplates hatte ich mir wirklich irgendwie falsch gemerkt.
Naja dank euch wurde dieser Misstand beseitigt
Nochmal danke
-
nur mal eine frage...
das ganze mag ja gut funktionieren, solange count konstant ist und vorm compilen eingegeben wird, aber ist diese lösung nich ...ähm etwas gefräßig, was speicherverbrauch angeht? also, ich meine, wenn du da count=1000 eingibst, erzeugt ja der compiler nach deiner template 1000 funktionen... (oder??
) und variable potenz kannst du dann auch nicht übergeben... 
warum nicht lieber:
template <class T> T potentize(T value, unsigned int counter){ if(counter==1){ return value; }else{ return value*potentize(value, counter--); } }wenn ich irgendwie grad quatsch rede, dann wär ich glücklich wenn ihr mir erklären würdet,, was an counter als template-parameter so entscheidend besser sein soll... :p
-
Andrey schrieb:
also, ich meine, wenn du da count=1000 eingibst, erzeugt ja der compiler nach deiner template 1000 funktionen...
Im Idealfall nicht. Der Compiler erkennt nämlich durchaus, dass das ganze konstant ist und wird das ganze zur Compilezeit auswerten. Dadurch wird letztendlich *ein* Wert in der resultierenden Datei stehen. Und da ist auch schon der Vorteil dieser Methode sichtbar: Es ist verdammt effizent, denn das Ausrechnen braucht zur Laufzeit *keine* Zeit.
Abgesehen davon wird man mit count=100 wahrscheinlich einige Probleme haben, da die Compiler ab einer gewissen Verschachtelungstiefe nicht mehr mitmachen. Der Standard verlangt außerdem auch nur, dass ein Compiler viel weniger Verschachtelungstiefen zwingend beherrscht (AFAIR 17).
-
Andrey schrieb:
wenn ich irgendwie grad quatsch rede, dann wär ich glücklich wenn ihr mir erklären würdet,, was an counter als template-parameter so entscheidend besser sein soll... :p
Das Ergebnis steht zur Compile-Zeit fest und nicht wie bei deiner Variante zur Laufzeit

-
Andrey schrieb:
warum nicht lieber:
template <class T> T potentize(T value, unsigned int counter){ if(counter==1){ return value; }else{ return value*potentize(value, counter--); } }Hmm, wenn Du schon eine rekursive Lösung haben willst (was IMHO gut ist!), dann mach sie besser endrekursiv, das kann der Compiler ebenfalls optimieren, und zwar so, dass im Maschinencode keine Rekursion mehr steht sondern eine "konventionelle" Schleife, was ebenfalls effizienter ist.
unsigned power(unsigned value, unsigned counter, unsigned accu = 1) { if (counter == 0) return accu; else return power(value, counter - 1, accu * value); }(Zum Thema Endrekursion siehe Wikipedia.)
-
aha... schon eine tolle sache... aber ich kann mir im moment irgendwie nicht so wirklich vorstellen, wozu man sowas beim potenzieren gebrauchen kann... dann kann man sich ja n taschenrechner schnappen und den wert direkt eintippen, oder sich halt n kleines programmchen schreiben, das von mir aus 8x8 matrizen multipliziert, und dann den vorberechneten wert da einsetzen... dann muss man zumindest nicht beim kompillieren jedes mal eine halbe stunde warten, bis der compiler mit den ganzen rechenaufgaben fertiggeworden ist

\edit: dieser beitrag bezieht sich auf den vorletzten beitrag

-
Andrey schrieb:
warum nicht lieber:
template <class T> T potentize(T value, unsigned int counter){ if(counter==1){ return value; }else{ return value*potentize(value, counter--); } }also der code hat noch nen kleinen schönheitsfehler: er endet nämlich, sofern counter nicht zu beginn 1 ist, in einer endlosschleife...
-
erstens wollt ich das machen, um mal ein bissl Metaprogrammierung zu machen, auch wenn es nicht sooo viel Sinn an der Stelle macht^^
Aber wie soll man sich daran gewöhnen, wenn man nicht auf mal im kleinen anfängt.zweitens Werte von 1000 oder so kommen da nicht vor:
@konrad: nur der Exponent ist konstant, nicht der eigentliche Wert.
Ziel ist folgendes: ich arbeite grad an einer Approximation. und da habe ich ziemlich viele Werte, die ich oft aussummieren, quadrieren oder auch mal ^3 und 4 nehmen muss und dann wieder summieren oder multipliziern usw.
Ich habe aber nur Ganzzahl-Exponenten. pow ist drauf aufgelegt mit Fließkommazahlen zu arbeiten und da nehme ich an value * value ist schneller, als wenn ich pow(value,2.0) mache (value ist immer double)Nun durch die vielen Werte will ich gern stl::transform nehmen für solche Sachen, brauche dann also Funktionsobjekte. Und damit ich mir nicht für 2,3,^4 jedesmal so ne kleine Klasse schreiben muss, wollt ich halt gerne das Template, was wir dann das value*value* .... generiert. Ist der ganze Hintergrund.
edit:
wenn ich irgendwie grad quatsch rede, dann wär ich glücklich wenn ihr mir erklären würdet,, was an counter als template-parameter so entscheidend besser sein soll... :p
Durch das counter als Templateargument und dem inline müsste der eigentlich zum Schluss wirklich ein "value*value*..." draus machen und halt nicht diesen rekursiven Funktionsaufruf.
-
Pellaeon schrieb:
Nun durch die vielen Werte will ich gern stl::transform nehmen für solche Sachen, brauche dann also Funktionsobjekte.
Dann schreib auch eine Klasse und keine Funktion:
template<typename T, int c> struct Pow { T operator()(T x) const { return Pow< c / 2 >()( x ) * Pow< ( c - 1 ) / 2 >()( x ) * x; } }; template<typename T> struct Pow< T, 0 > { T operator()(T) const { return 1; } };
-
erstens schon längst gemacht, siehe Seite 1 unter es funzt
(eine Klasse sollte eh noch kommen nur bei Template-Funktionen sucht er sich halt selber den Typ raus was praktisch ist)zweitens was soll denn das sein?
return Pow< c / 2 >()( x ) * Pow< ( c - 1 ) / 2 >()( x ) * x;Bringt bei mir nur nen Compilefehler hab das an der Stelle so gemacht:
return value * Potentize<T,count - 1>().operator ()(value);
-
Pellaeon schrieb:
erstens schon längst gemacht, siehe Seite 1 unter es funzt
(eine Klasse sollte eh noch kommen nur bei Template-Funktionen sucht er sich halt selber den Typ raus was praktisch ist)zweitens was soll denn das sein?
return Pow< c / 2 >()( x ) * Pow< ( c - 1 ) / 2 >()( x ) * x;Bringt bei mir nur nen Compilefehler hab das an der Stelle so gemacht:
return value * Potentize<T,count - 1>().operator ()(value);Hab ich wohl übersehen. Es muss nat.
Pow< T, c / 2 >()( x ) * Pow< T, ( c - 1 ) / 2 >()( x ) * x;heißen. So werden weniger Templates instantiiert.