Forum: Compiler & IDEs a hoch b programmieren


von steht auf dem Schlauch (Gast)


Lesenswert?

Sorry for being doof, aber ich steh grad auf dem Schlauch! Wie 
programmiere ich in C a hoch b.  bzw.  a hoch 2 ?

von Peter II (Gast)


Lesenswert?

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

von Dirk B. (dirkb2)


Lesenswert?

steht auf dem Schlauch schrieb:
> Wie programmiere ich in C  ...  a hoch 2

Am einfachsten als (a*a)

von Thomas K. (feynman)


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).

von Dirk B. (dirkb2)


Lesenswert?

Thomas K. schrieb:
> a^b

Ist etwas unglücklich, da ^ in C eine andere Bedeutung hat. Und hier 
geht es ausdrücklich um C

von Thomas K. (feynman)


Lesenswert?

Richtig! Bitte meinen beschrieben Text nicht in c-Notation lesen. Das 
Dach "^" steht für "hoch", nicht für XOR.

von Helmut L. (helmi1)


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.

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))

von Walter (Gast)


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)

von Sebastian (Gast)


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.

von Markus F. (mfro)


Lesenswert?

Welche Zielplattform, wie schnell muß es sein, wieviel Speicher hast Du 
zur Verfügung, was ist der Zieldatentyp?

von Udo S. (urschmitt)


Lesenswert?

Walter schrieb:
> dann lieber gleich
> double pow(double x, double y)

Wie würdest du den Algorithmus implementieren?

von Sebastian V. (sebi_s)


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.

von Walter (Gast)


Lesenswert?

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?

von Andreas S. (asc)


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.

: Bearbeitet durch User
von Sebastian (Gast)


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.

von steht auf dem Schlauch (Gast)


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 
:-)

von Karl H. (kbuchegg)


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.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Sollten 16 Bit Ergebnis ausreichend sein, ist eine Lookup-Table die 
einfachste (und mit Abstand schnellste) Lösung.

von Dieter F. (Gast)


Lesenswert?

Prima Lösungsvorschläge - ob es dem Troll-Gast auch gefällt?

Aber für alle anderen - durchaus belehrend :-)

von Yalu X. (yalu) (Moderator)


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.

von Johann L. (gjlayde) Benutzerseite


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:

: Bearbeitet durch User
von Andreas S. (asc)


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.

: 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
Noch kein Account? Hier anmelden.