a hoch b programmieren

#3966338
Lesenswert?

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).
Gast #3966716
Lesenswert?

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)
Gast #3967028
Lesenswert?

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.
#3967773
Lesenswert?

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.
#3968800
Lesenswert?

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.
Gast #3968848
Lesenswert?

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.
Gast #3969737
Lesenswert?

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 
:-)
#3969745
Lesenswert?

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.
Moderator #3969856
Lesenswert?

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.
Persönliche Seite #3970058
Lesenswert?

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:
#3970080
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren