Potenzberechnung
-
Hallo zusammen,
Ich soll für meine Lehre ein Programm schreibe das hoch rechnen kann. Nun, ist mir das fast gelungen, bis auf das rechnen mit Kommazahlen und negativen Exponenten. Hier meine Lösung, vielleicht findet jemand meine/n Fehler.
/*** Include Files ***********************************************************/ #include <stdlib.h> /* Funktionsbibliothek: Hilfsfunktionen */ #include <stdio.h> /* Funktionsbibliothek: Standard Ein- Ausgabe */ /*** Globale Deklarationen und Definitionen **********************************/ double Basis = 0; double Potenztemp = 0; double Potenz; double Resultat = 1; /*** Funktions-Deklarationen *************************************************/ /******************************************************************************* ******************************* HAUPTPROGRAMM ********************************** *******************************************************************************/ int main(void) { // lokale Variablen /* Intro --------------------- */ puts ("*****************************************************************"); puts ("* Das ist ein Potenzrechner *"); puts ("*****************************************************************"); /* Verarbeitung und Ausgabe -------------- */ printf("Bitte geben sie die Basis ein: "); scanf("%d",&Basis); printf("Bitte geben sie die Potenz ein: "); scanf("%ds",&Potenz); Potenztemp = Potenz; while(Potenztemp != 0){ Resultat = Resultat*Basis; if(Potenz < 0){ Potenztemp++; } else { Potenztemp--; } } if(Potenz <= -1 ){ Resultat = 1 / Resultat; } /* Ausgabe ------------------- */ printf("Das Resultat von %f hoch %f ist %f\n",Basis,Potenz,Resultat); system ("PAUSE"); /* Nur während der Entwicklungsphase, später löschen! */ return (0); }
Mit freundlichen Grüssen,
Nerwan(Brian)
-
Schau dir nochmal die Referenz zu scanf an und wozu %d da verwendet wird.
Und verzichte auf die globalen Variablen.
-
Hi,
dein Formatstring passt nicht zur Eingabe.
Ein %d erwartet eine Ganzzahl.
http://www.cplusplus.com/reference/cstdio/scanf/
Schreib malscanf("%lf",&Basis);
-
"%d" liest dezimale Ganzzahlen in einen int. Ein kleines Wunder (oder auch eher Pech, da du nichts bemerkst), dass dein Programm überhaupt irgendetwas macht. "%lf" ist der scanf-Formatspezifizierer für double.
Gewöhn dir globale Variablen ganz schnell wieder ab. Dringend!
Als Exponent solltest du nur Ganzzahlen zulassen, da dein Algorithmus nicht für reelle Exponenten funktioniert.
edit: Zu langsam.
-
SeppJ schrieb:
"%d" liest dezimale Ganzzahlen in einen int. Ein kleines Wunder (oder auch eher Pech, da du nichts bemerkst), dass dein Programm überhaupt irgendetwas macht. "%lf" ist der scanf-Formatspezifizierer für double.
Gewöhn dir globale Variablen ganz schnell wieder ab. Dringend!
Als Exponent solltest du nur Ganzzahlen zulassen, da dein Algorithmus nicht für reelle Exponenten funktioniert.
edit: Zu langsam.
Vielen Dank für die schnellen Antworten. Ich muss leider zugeben das ich wirklich vergessen habe die Datetypen bei scanf zu ändern.
Das Globale Variablen nicht gut sind ist mir klar, nur lernt man das bei uns im 1. Semester noch so und später wieder anders..
Vielen Dank nochmal.
PS: Wäre es schwierig den Algorithmus so anzupassen das er mit reellen Exponenten funktioniert?
-
Nerwan schrieb:
PS: Wäre es schwierig den Algorithmus so anzupassen das er mit reellen Exponenten funktioniert?
Ja und Nein. Was ist schwierig? Ist es mathematisch schwierig? Ja, der Stoff ist schon Oberstufe oder frühes Mathestudium. Aber kann man nachlesen. Ist der Algorithmus schwierig? Ja, einen funktionierenden, geschweige denn einen guten Algorithmus selber zu entwickeln ist schwierig. Aber kann man nachlesen. Einen nachgelesenen Algorithmus selber implementieren? Das kann jeder.
-
SeppJ schrieb:
edit: Zu langsam.
Dafür ausführlich.
-
Wie ist das gemeint mit
SeppJ schrieb:
edit: Zu langsam.
und
DirkB schrieb:
Dafür ausführlich.
?
Sry, meine Programmier Fähigkeiten sind nicht die besten, ich lerne es nun seit einem viertel Jahr C und es ist nicht mein liebstes Fach in der Schule.
-
SeppJ schrieb:
Einen nachgelesenen Algorithmus selber implementieren? Das kann jeder.
nein.
-
Nerwan schrieb:
Wie ist das gemeint mit ....?
Vor SeppJs Antwort waren schon zwei andere Antworten.
Dafür hat er aber mehr erklärt.
-
Hier einige Anmerkungen zur (hoffentlich inzwischen funktionierenden) Lösung:
Erst einmal das ganzzahlige Problem:
1. Die Potenzfunktion steigt sehr schnell an. Daher kommt es möglicherweise (double Exponent bei 308) zu einem Überlauf und das Programm stürzt ab. Wird dagegen gleich bei negativer Hochzahl die Division gewählt, kommt es zu einem Unterlauf auf 0, so dass das Programm nicht abstürzt, also "robuster" ist.
2. Willst Du Deinen Lehrer überraschen, dann probiere es einmal mit der "Ägyptischen Bauernmultiplikation". Beispiel
x^5 = x^4 * x = (x^2)^2 * x = (x*x)*(x*x) * x
Zerlegt man also die Hochzahl in Zweierpotenzen, dann kann man Zwischenwerte bilden und so Multiplikationen einsparen:
`x^10 = x^8 * x^2 = (x4)2 * x^2 = ((x2)2)^2 * x^2
x^10 = (x5)2 = ` das hatten wir schon (und sieht unheimlich rekursiv aus)
Ich habe mich hoffentlich nicht vertippt. Also
1. Bilde das Quadrat
2. Dividiere (ganzzahlig) die Hochzahl
3. Ist sie größer als 1, dann quadriere das Quadrat
4. Dividiere die Hochzahl wieder durch 2
5. Ist das Ergebnis irgendwann 1, dann multipliziere noch einmal mit x3. Reelle Exponenten
Die allgemeine Potenz z = x^y ist numerisch folgendermaßen zu rechnen
z = e ^ (y*ln(x))
Dazu benötigst Du also die exp- und die ln-Funktion aus math.h.
Da würde ich vorsichtshalber noch einmal in die Aufgabenstellung schauen oder den Lehrer befragen.
-
Waldschrat schrieb:
Dazu benötigst Du also die exp- und die ln-Funktion aus math.h.
Ein bisschen witzlos, oder? Da kannst du auch gleich pow nehmen. Es ginge doch darum, diese selber zu programmieren (und das ist dann schon etwas härter, siehe oben).
-
Ohne nun über die tatsächlich internen Funktionen und ihr Zusammenspiel streiten zu wollen, sollte der Beitrag demonstrieren, dass die allgemeine Potenz nicht so einfach mit elementaren Rechenoperationen zu berechnen ist.
Im letzten (soeben heftig kritisierten) Abschnitt meines Beitrags habe ich dargelegt, wie es intern berechnet wird.
Wenn ich also einfach weiterdenken, lese ich in dieser Community immer wieder die Frage nach der Reihenentwicklung der Exponential- bzw. der Logarithmusfunktion. Deshalb habe ich mir erspart, dies noch einmal darzulegen.
Es tut mir leid, wenn das bei den Lesern nicht so richtig angekommen ist. Es müssen in der EDV bei allen Funktionen schnell konvergierende Approximationen (meist Polynome, rationale Funktionen, Kettenbrüche usw.) gefunden werden, die durch elementare Rechenoperationen dem gesuchten Wert möglichst nahe kommen. Ggf. müssen zwei oder mehr Funktionen dazu herhalten, wie dargestellt. pow ist keine eigenständige Funktion sondern nur eine Verpackung dafür.
Vielleicht hier noch ein wenig Theorie:
Die negativen Ganzzahlexponenten werden durch Divisionen erzeugt, was der Op richtig erkannt hat.
Die rationalen Exponenten führen zur Wurzelbildung einer Ganzzahlpotenz, also x ^ 3/2 ist die Quadratwurzel aus x^3.
Die Quadratwurzel wird in den Anfängervorlesungen gern mit dem Babylonischen Wurzelziehen (auch: Verfahren von Heron) programmiert. Schon an diesem Beispiel sieht man, dass die allgemeine Potenz nicht elementar berechnet werden kann.
Ich entschuldige mich daher noch einmal, dass aus meinem letzten Teil nicht deutlich wurde, dass es nicht geht. Vielleicht habe ich aber auch nur eine solche Aussage bei den vorangegangenen Beiträgen übelesen.
Können wir uns daher darauf einigen:
1. In vielen Beiträgen in diesem Forum findet der Op die Hinweise, wie man ln und exp mit elementaren Rechenoperationen löst.
2. Setzt er die so gewonnenen Zwischenergebnisse in die Formel ein, dann hat er seine gewünschte Lösung.
-
Ich glaube, du liest zu viel Kritik in meinen Beitrag hinein.