Sorry for being doof, aber ich steh grad auf dem Schlauch! Wie programmiere ich in C a hoch b. bzw. a hoch 2 ?
steht auf dem Schlauch schrieb: > Sorry for being doof, aber ich steh grad auf dem Schlauch! Wie > programmiere ich in C a hoch b. bzw. a hoch 2 ? http://en.cppreference.com/w/cpp/numeric/math/pow
a^b ist nix anderes wie a genau b mal mit sich selbst zu multiplizieren. a^2 = a*a du machst also ne schleife, in der du b Schleifendurchgänge eine Variable (die mit 1 initialisiert ist) immer wieder mit a multiplizierst. Auf die Dateitypen achten (da entsteht schnell ne Longzahl).
Thomas K. schrieb: > a^b Ist etwas unglücklich, da ^ in C eine andere Bedeutung hat. Und hier geht es ausdrücklich um C
Richtig! Bitte meinen beschrieben Text nicht in c-Notation lesen. Das Dach "^" steht für "hoch", nicht für XOR.
Thomas K. schrieb: > du machst also ne schleife, in der du b Schleifendurchgänge eine > Variable (die mit 1 initialisiert ist) immer wieder mit a > multiplizierst. Und wie machst du das wenn b eine gebrochen Zahl ist? Man kann auch ueber Logarythmen zum Ergebnis kommen. y = a^b kann man auch so ausrechnen: y = exp(b x ln(a))
Helmut Lenzen schrieb: > Und wie machst du das wenn b eine gebrochen Zahl ist? > > Man kann auch ueber Logarythmen zum Ergebnis kommen. > > y = a^b kann man auch so ausrechnen: > > y = exp(b x ln(a)) und wie rechnest du e hoch (b*ln(a)) aus? Ich sehe da keinen Gewinn, dann lieber gleich double pow(double x, double y)
Thomas K. schrieb: > du machst also ne schleife, in der du b Schleifendurchgänge eine > Variable (die mit 1 initialisiert ist) immer wieder mit a > multiplizierst. Gilt, wie von Helmut erwähnt, nur wenn b eine ganze Zahl ist. In diesem Fall, und wenns die auf Effizienz ankommt, b groß sein kann und/oder der Datentyp von a teuer zu multiplizieren ist, kannst du auch ein Paar Multiplikationen zusammengruppieren, in einer temporäen Variable speichern und dann damit weiter multiplizieren. Braucht dann nur noch O(log b) Multiplikationen.
Welche Zielplattform, wie schnell muß es sein, wieviel Speicher hast Du zur Verfügung, was ist der Zieldatentyp?
Walter schrieb: > dann lieber gleich > double pow(double x, double y) Wie würdest du den Algorithmus implementieren?
Walter schrieb: > und wie rechnest du e hoch (b*ln(a)) aus? > > Ich sehe da keinen Gewinn, dann lieber gleich > double pow(double x, double y) Für die Exponentialfunktion und den natürlichen Logarithmus gibt es aber Reihendarstellungen. Damit hat man schonmal einen einfachen (wenn auch nicht besonders effizienten) Weg diese Funktionen auszurechnen. Vermutlich gibts auch einen Weg direkt a^b auszurechnen aber dazu konnte ich auf die schnelle nichts finden.
Udo Schmitt schrieb: >> dann lieber gleich >> double pow(double x, double y) > > Wie würdest du den Algorithmus implementieren? gar nicht, ich würde #include <math.h> c = pow(a,b); schreiben. Erfindest Du etwa das Rad jedes Mal neu?
Walter schrieb: > Udo Schmitt schrieb: >>> dann lieber gleich >>> double pow(double x, double y) >> >> Wie würdest du den Algorithmus implementieren? > > gar nicht, ich würde > > #include <math.h> > > c = pow(a,b); > > schreiben. Erfindest Du etwa das Rad jedes Mal neu? Der Fragesteller haette sicherlich nicht gefragt, wenn er denn so einfach eine math lib haette benutzen koennen.
:
Bearbeitet durch User
Andreas S. schrieb: > Der Fragesteller haette sicherlich nicht gefragt, wenn er denn so > einfach eine math lib haette benutzen koennen. Die Frage war: > Wie programmiere ich in C a hoch b. math.h ist eine C Standardbibliothek. Also ist die Antwort doch gar nicht so schlecht. > Der Fragesteller haette sicherlich nicht gefragt, > wenn er denn so einfach eine math lib haette benutzen koennen. > Sorry for being doof, aber ich steh grad auf dem Schlauch! Vielleicht hat er nur die richtige Funktion überlesen, weil er nach "exponential" und nicht nach "power" gesucht hat? Jetzt wär langsam mal eine Rückmeldung des Fragestellers interessant, damit wir wissen, ob wir aufhören können noch mehr Vorschläge zu sammeln.
Sebastian schrieb: > Jetzt wär langsam mal eine Rückmeldung des Fragestellers interessant, > damit wir wissen, ob wir aufhören können noch mehr Vorschläge zu > sammeln. Sorry für nicht wieder melden, war im Stress! Meine Frage war mit dem Hinweis auf "pow(x,y)" in der ersten Antwort geklärt! Ich wusste einfach nicht wonach googlen bzw. im Buch suchen... => auf dem Schlauch stehen :-)
pow ist aber die deutlich schlechteste Variante, wenn es darum geht lediglich Quadrate auszurechnen. Bei kleinen ganzzahligen Exponenten einfach entsprechend oft Multiplizieren. Ja nachdem, was man konkret rechnet, kann auch bei mehreren Potenzen in einer Formel ein Horner-Schema abgebracht sein.
:
Bearbeitet durch User
Sollten 16 Bit Ergebnis ausreichend sein, ist eine Lookup-Table die einfachste (und mit Abstand schnellste) Lösung.
Prima Lösungsvorschläge - ob es dem Troll-Gast auch gefällt? Aber für alle anderen - durchaus belehrend :-)
steht auf dem Schlauch schrieb: > Ich wusste einfach nicht wonach googlen Klar wusstest du das, du bist nur nicht auf die Idee gekommen, es auch tatsächlich auszuprobieren ;-) Google doch einfach mal nach dem Titel deines Threads. Schon das 3. und das 4. Suchergebnis liefern bei mir den Hinweis auf die pow-Funktion. Ohne diesen Thread (der als 1. Ergebnis ausgegeben wird) würden sie jeweils sogar noch einen Platz nach oben rücken.
Walter schrieb: > Udo Schmitt schrieb: >>> double pow(double x, double y) >> >> Wie würdest du den Algorithmus implementieren? > > gar nicht, ich würde > > #include <math.h> > > c = pow(a,b); > > schreiben. Erfindest Du etwa das Rad jedes Mal neu? Solche Rädchen werden ständig neu erfunden, egal wie eckig sie auch sein mögen. Es hält sich nämlich ebenso hartnäckig und unausrottbar das Gerücht, Compilerbauer und Autoren von Standardbibliotheken seinen ebenso faul und planlos wie manche Fragesteller in manchen Internetforen... Karl Heinz schrieb: > pow ist aber die deutlich schlechteste Variante, wenn es darum geht > lediglich Quadrate auszurechnen. Fütter den gcc deiner Wahl einfach mal mit -O2 -ffast-math und:
1 | #include <math.h> |
2 | |
3 | float quadrf (float x) { return powf (x, 2); } |
4 | float cubicf (float x) { return powf (x, 3); } |
5 | double quadr (double x) { return pow (x, 2); } |
6 | double cubci (double x) { return pow (x, 3); } |
Wobei ich einem x * x gerne den Vorzug gegenüber dem pow (x, 2) gebe, ist m.E. besser lesbar. > Bei kleinen ganzzahligen Exponenten einfach entsprechend oft > Multiplizieren. [senf] Bei betragsmäßig kleinen, ganzzahligen Exponenten. Bei natürlichen Exponenten: einmal weniger oft multiplizieren wie der Exponent angibt. Bei 0 gibt man 1 zurück. Und bei negativen Exponentenso das Dividieren nicht vergessen. [/senf] Dieses Verfahren ist allerdings langsam und zudem schlechter konditioniert, da mehr (grob exponentienn mit n) Operationen gemacht werden als notwendig. Mit dem Rüstzeug zur Lösung des Problems wappnet einen die Grundschule: 42 * 83 berechnet man nicht, indem man 42 mal 83 addiert oder 83 mal 42 addiert, sondern verwendet ein auf Dezimalstellen basierendes Verfahren: Schriftliche Multiplikation. Überträgt man das von Basis 10 auf Basis 2 und von einem Faktor auf den Exponenten, dann gelangt man zu: > bei mehreren Potenzen in einer Formel ein Horner-Schema > angebracht sein. In dem Fall nennt sich das hochtrabend "Schnelle" Exponentiation: http://de.wikipedia.org/wiki/Schnelle_Exponentiation Vor allem in algebraischen Strukturen ist diese Verfahren unentbehrlich, denn 1) Lassen sich oft exp oder ln nicht sinnvoll definieren 2) Sind die Exponenten oft sehr groß, z.B. bei kryptologischen Anwendungen. Werden dazu Zahlen bis 10^100 verwenden, liegen die Exponenten in der gleichen Größenordnung 3) Für das Verfahren brauch man nicht mehr als eine assoziative Verknüpfung. (Für x^0 noch ein neutrales Element und für negative Exponenten Invertierbarkeit von x). Sebastian V. O. schrieb: > Walter schrieb: >> und wie rechnest du e hoch (b*ln(a)) aus? >> >> Ich sehe da keinen Gewinn, dann lieber gleich >> double pow(double x, double y) > > Für die Exponentialfunktion und den natürlichen Logarithmus gibt es aber > Reihendarstellungen. Damit hat man schonmal einen einfachen (wenn auch > nicht besonders effizienten) Weg diese Funktionen auszurechnen. Wenn man diese Reihendarstellung blind anwendet dann gewinnt man damit keinen Blumentopf, vor allem nicht gegenüber pow. Versuch max exp(-100) mit Taylor auszurechenen. Für ln sieht's noch übler aus: die Mercatorreihe konvergiert nur in (-1,1]. Damit hat man zwar ln in (0,2] aber die Konvergenz in Richtung Konvergenzradius wird so grottig, dass es nicht nur eine Frage der Effizienz wird, sonder ob das Ergebnis überhaut noch etwas mit ln zu tun hat. Siehe Beispiel oben mit exp(-100). Besser führt man ln auf arcoth (AReaCOTangensHyperbolicus) zurück und stellt x dar als m·B^k mit ganzzahligem k und einer Konstanten B. m lässt sich dann leicht aus x berechnen, und k wählt man so, dass m nahe bei 1 liegt. ln (x) wird dann zu
wobei man die Konstante ln(B) im Algorithmus vorhält. Bei Fließkommazahlen hat man B = 2 oder 10 bei decimal float und m als Mantisse bereits frei Haus. Verbleibt die Berechnung von e^x. Günstig scheint auch hier eine andere Darstellung von x. Ins Auge springt
Damit ist
r tariert man so aus, dass es betragsmäßig klein wird, d.h. nahe am Entwicklungspunkt 0 von exp zu liegen kommt:
Wiederum sind 2 und 10 heiße Kandidaten für B. Ist diese Darstellung des Ergebnisses nicht vorteilhaft, geht auch B = e. Das führt effektiv zu
mit einer ganzen Zahl n. Mit n bringt man das Argument von exp in einen Bereich, in dem es vernünftig konvergiert und konditioniert. n sollte also (betragsmäßig) nicht zu klein und nicht zu groß werden. Gehen wir davon aus, dass die Taylorreihe für exp mit |x| < 10 vernünftig konditioniert, und will man exp(230) berechnen (was ca. 10^100 wird) dann wäre n = 23, was man mit "schneller" Exponentiation berechnet. Besser noch ist n = 32, d.h.
Mit y = exp (x/n) braucht's bis zum Endergebnis dann noch 5 Multiplikationen:
:
Bearbeitet durch User
Sebastian schrieb: > Andreas S. schrieb: >> Der Fragesteller haette sicherlich nicht gefragt, wenn er denn so >> einfach eine math lib haette benutzen koennen. > > Die Frage war: >> Wie programmiere ich in C a hoch b. > > math.h ist eine C Standardbibliothek. Also ist die Antwort doch gar > nicht so schlecht. Nun ja, programmiert hat er es so ja nicht wirklich. Da wir uns hier im Mikrocontroller Forum bewegen, bin zumindest ich davon ausgegangen, dass in seiner (Was auch immer)Umgebung eben nur eingeschränkte Moeglichkeiten zur Verfuegung stehen und er die benoetigten Funktionen selber erzeugen muss. Es ist nicht unueblich, sowas in (Pseudo) C Code zu gestalten und dann "wandeln" zu lassen.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.