[C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

B

boss3D

Guest
[C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Hi @ all!

Ich brauche für einen großen Code eine kleine Funktion, die mir Hochzahlen berechnet. Da ich lieber mit einzelnen "Bäumen" arbeite, als mit dem ganzen "Wald" auf einmal, versuche ich, diese kleine Funktion erst einmal unabhängig vom großen Code zu schreiben und erst, wenn sie funktioniert, zu implementieren. Die Funktion pow der Bibliothek math.h soll/darf dabei nicht verwendet werden ...

Eigentlich habe ich schon ein Bisschen Ahnung von C, aber irgendwie komme ich nicht dahinter, wieso mein kleiner Code nicht die gewünschten Ergebnisse liefert:

Code:
#include <stdio.h>

int exp(int a, int b) {
    int i=1;

    for (i; i<=b; i++) {
        a*=a;
    }

    return a;
}

int main(void) {
    int basis=0, exponent=0;

    printf("Please enter any value for basis: ");
    scanf("%d", &basis);
    printf("Please enter any value for exponent: ");
    scanf("%d", &exponent);
    printf("\n%d^%d = %d\n\n", basis, exponent, exp(basis, exponent));

    return 0;
}
Vielleicht sieht von euch wer den Fehler?!

Danke für baldige Antworten!
 
Zuletzt bearbeitet:
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Moin

Code:
#include <stdio.h>

int exp(int a, int b) {
    int i=1;
    [COLOR=red]int x=a;
    for (i; [COLOR=red]i<b; i++) {
        [COLOR=red]x=[COLOR=red]x*a;
    }

    return [COLOR=red]x;
}

int main(void) {
    int basis=0, exponent=0;

    printf("Please enter any value for basis: ");
    scanf("%d", &basis);
    printf("Please enter any value for exponent: ");
    scanf("%d", &exponent);
    printf("\n%d^%d = %d\n\n", basis, exponent, exp(basis, exponent));

    return 0;
}
Mit den roten Änderungen klappt das jedenfalls bei mir.
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Der Fehler liegt im a*=a.

Das a verändert sich und bleibt nicht konstant.
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Hier eine aus meiner kleinen mathe-lib :)

Code:
public static double exp(double k, int n)
            {
                double erg = 1.0d;

                if (n > 0)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = k;
                    while (n++ < 0)
                    {
                        erg *= 0.1d;
                    }
                }
                else if (n == 1)
                { return k; }

                return erg;
            }
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Der Fehler liegt im a*=a.

Das a verändert sich und bleibt nicht konstant.
Ok, was du meinst verstehe ich, aber wieso funktioniert dann die Lösung von XT1024, der ja nichts anderes macht, als x gleich a zu setzen? Ist das so zu verstehen, dass x den (Start-)Wert von a bekommt, aber an einer anderen Adresse im Speicher ablegt und ich dann den Wert zurückgebe, der an der Adresse von x liegt?

Und wieso i<b? Es soll ja bis zur gewünschten Hochzahl gerechnet werden und nicht schon eins vorher aufgehört werden. Wieso funktioniert das mit i<b, aber nicht mit i<=b?
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Mal abgesehen davon, dass die die Definition von x^0 = 1 vergessen hast, steht der Fehler im 3. Posting.

Du rechnest bei 2^2

2 * 2 = 4

Bei 3^3 rechnest du im 1. Schleifendurchlauf

3 * 3 = 9 aber im 2. mit dem ERGEBNIS des 1. weiter:

9 * 9 = 81

Du musst dir die Basis in einer extra Variable festhalten. Außerdem glaube ich, dass deine Schleifenabbruchbedingung nicht stimmt. (Oh steht auch schon in rot da)
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

dass die die Definition von x^0 = 1 vergessen hast
Stimmt. Aber der Fall kommt im großen Programm eh nicht vor. [Edit] Hab's jetzt trotzdem schnell so geändert, dass der Fall auch berücksichtigt würde. ;)
----------------------

Ich habe das jetzt in den großen Code implementiert, nur leider liefert dieser noch nicht ganz das gewünschte Ergebnis. Das muss allerdings nicht an der kleinen Hochzahlfunktion liegen!

Es geht darum, folgende Ausgabe durch mehrere Berechnungen und geschickte Formatierung zu erreichen:

Capture1.JPG

Die genäherten Werte sollen dabei über die Taylor-Reihe berechnet werden:

Capture2.JPG

Meine Ausgabe kommt dem schon relativ nahe, aber stimmt noch nicht zu 100 % mit der Vorgabe überein:

Capture3.JPG

Hier mein Code:

Code:
#include <stdio.h>
#include <math.h>

int fakultaet(int x) { /* Fakultät rekursiv */
    if (x == 0)
        return 1;
    else
        return (x * fakultaet(x-1));
}

int hochzahl(int a, int b) { /* Berechnung der Hochzahl; eingesetzt werden die Werte 'start' und 'hoch' aus Funktion exp_genaehert; start steht für x in der Taylorreihe */
    int i=1, j=a;
    
    if (b == 0) {
        return 1;
    } else {
        for (i; i<b; i++) {
            j*=a;
        }
    }
    
    return j;
}

double exp_exakt(int start) { /* Berechnung des exakten x */
    double exakt=0.0;

    exakt=exp(start);

    return exakt;
}

double exp_genaehert(int start, int end) { /* Berechnung des genäherten x durch die Taylorreihe */
    int j=0, hoch=0;
    double genaehert=1.0+start, i=0.0;

    for (hoch=2, j=2; hoch<=end, j<=end; hoch++, j++) { /* 'hoch' steht für Hochzahl; vom jeweiligen j soll in jedem Schleifendurchlauf die Fakultät berechnet werden */ 
        i=fakultaet(j); 
        genaehert += ((1/i)*(hochzahl(start, hoch))); /* Berechnung der Taylorreihe */ 
    }

    return genaehert;
}

int main(void) {
    int start=0, end=10, inc=2;
    double err_bound=0.0010000000;

    printf("Naeherungsweise Berechnung von exp(x)\n\n");
    printf("Startpunkt: %d\n", start);
    printf("Endpunkt: %d\n", end);
    printf("Schrittweite: %d\n", inc);
    printf("Fehlerschranke: %.10lf\n\n", err_bound);
    printf(" x : exp(x) genaehert : exp(x) exakt     : Fehler\n");
    printf("============================================================\n");
    for (start; start<=end; start+=inc) {
        printf("%2d : %16.10lf : %16.10lf : %.10e\n", start, exp_genaehert(start, end), exp_exakt(start), (exp_exakt(start)-exp_genaehert(start, end))); /* Ausgabe sämtlicher Ergebnisse der Funktionen für den jeweiligen Start-Wert */
    }
    putchar('\n');

    return 0;
}
Wodurch kommen die Abweichungen zustande? Irgendwie muss es wohl an meiner Berechnung der Taylor-Reihe liegen, aber ich finde den Fehler nicht ...
 
Zuletzt bearbeitet:
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Du kannst die TR auch einfacher berechnen:

1 + x*(1 + x/2 * (1 + x/3 * (... (1 + x/n))...))

Dann fängst du "von innen" an zu rechnen, also du fängst mit 1 + x/n an und arbeitest dich dann nach außen bis 1 + x vor. Damit sparst du dir schon mal die Fakultät und das Potenzieren.
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Hier eine aus meiner kleinen mathe-lib :)

Code:
public static double exp(double k, int n)
            {
                double erg = 1.0d;

                if (n > 0)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = k;
                    while (n++ < 0)
                    {
                        erg *= 0.1d;
                    }
                }
                else if (n == 1)
                { return k; }

                return erg;
            }

Was spuckt das Programm aus wenn du 2^(-1) hast oder 2^(-10)?

Dein Code funktioniert nur bei 10er Potenzen und 0.
 
Zuletzt bearbeitet:
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Was spuckt das Programm aus wenn du 2^(-1) hast oder 2^(-10)?
Dein Code funktioniert nur bei 10er Potenzen und 0.

Negative Potenzen sind ja eine Teilung durch 10, sprich 2^-1 ist dasselbe wie 2* (1 / 10^1) und 2^-2 wären dann gleich 2 * ( 1 / 10^2) usw.
Und das steht soweit ich das erkenne auch in seinem Code:
Code:
else if (n < 0) {     erg = k;     while (n++ < 0)    {       erg *= 0.1d;    } }


@fadade: du hast das jetzt ja mit " *= " gelöst, warum keine Rekursion?
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Dann lass mal den Code laufen. Wenn du 2^(1) einwirfst kommt 0.2 raus, was falsch ist.

-----

Eine rekursive Lösung wäre so:

Code:
double power(double x, int n)
{
    if (n>0)
        return x*power(x, n-1);

    else if (n==0)
        return 1;

    else
        return power(1/x, -n);
}
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

@JimSim: alles klar dann halt so :D
da muss fadade aber mal nachbessern (wenn er es für allgemeine zahlen haben möchte ...)

@nay: ich habe es jetzt nicht gemacht, aber wenn du 2^(1) haben möchtest, dann ist k=2 und n=1, sprich der Code spring hier rein:
Code:
if (n > 0) {     while (n-- > 0)      {         erg *= k;       }
dann verringert er n um ist (ist dann 0) und multipliziert erg (1.0) mit k(=2), dann ist in erg ne 2 drin und bei der nächsten prüfung der schleifenbedingung müsste er abbrechen und erg=2 zurückgeben --> 2^1 = 2
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Ich meine doch 2 hoch minus 1 :D

Da kommt man hier rein

Code:
else if (n < 0) {     erg = k;     while (n++ < 0)     {         erg *= 0.1d;     } }

und raus kommt 0.2. Es müsste 0.5 rauskommen.
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Ui ui ... jetz meld ich mich doch lieber nochmal, bevor hier ein Forenkrieg ausbricht :D
Der Code den ich geposted habe war vorhin so schön weit oben und ich hab das Kommentar nicht gelesen, in welchem ich eindeutig vermerkt habe, dass der Code nur für einen bestimmten Zweck bei mir gedacht ist.

Hier mal die "normale" exp-Funktion. Hat einen kleinen und doch großen Unterschied (da kommt auch etwas Rekrusion mit rein joffal ;) )

Code:
public static double exp(double k, int n)
            {
                double erg = 1.0d; // für k^0 vorgespeicherter Wert

                if (n == 1)
                { 
                    return k; 
                }
                else if (n > 1)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = 1 / exp(k, n);
                }
                
                return erg;
            }
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Es ist leider immer noch falsch :D Es muss heißen:
Code:
...

else if (n < 0)
{
     erg = 1 / exp(k, [B]-[/B]n);
}

...
Also es muss ein Minus vor das n sonst wird sich der CPU Lüfter bemerkbar machen ;)
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

oh tatsächlich! :fresse: :D
Zum Glück habe ich die Methode so in der Form noch gar nicht benutzt ...

Aber ist deine Frage wenigstens geklärt? ^^
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Ich verstehe, dass du die Funktion in Post #4 für einen bestimmten Zweck geschrieben hast aber ich weiß nicht genau warum du das so verwirrend verpackt hast :)
Mach doch eine Funktion posExp für Potenzen mit positivem Exponenten und eine andere Funktion eNeg, die das Komma einer Zahl nach links verschiebt.
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Hier den Fehler, der zu den Abweichungen vom "erwarteten" Ergebnis führt, zu suchen, hat eh keiner Lust, oder? :ugly: ;)
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Hier den Fehler, der zu den Abweichungen vom "erwarteten" Ergebnis führt, zu suchen, hat eh keiner Lust, oder? :ugly: ;)
Hast du das mal mit der "vereinfachten" TR versucht, die ich vorgeschlagen habe? Ich hatte mal ein Programm geschrieben, das auch 50% Abweichung bei den Berechnungen hatte, nur weil ich "falsch" addiert hatte (sehr kleine auf sehr große Werte gibt nur große Wert -> Müll). Eventuell kannst du mit der vereinfachten Berechnung schon dein Problem lösen
 
Zurück