Bruchrechnen in C

Scooopy

Grünschnabel
Hallo,

ich bräuchte mal ein bisschen Hilfe bzw. auch ein paar Tipps.
Folgendes Problem, wenn man einen Bruch eingibt erkennt er nicht, dass nur ein Bruch berechnet werden muss und nicht beide. Bsp. 3|2 + 7|4 = 6|4 + 7|4 = 13|4
Komme einfach nicht drauf wie ich es umschreiben kann.
Sonst wäre ich, glaube ich, soweit fertig. Evtl könnte man es ein bisschen besser umschreiben.

C:
#include <stdio.h>
main() {
    int zaehler1, zaehler2, nenner1, nenner2, zahl;
    int r = 0;
    int kgv;
marker:;
    printf("\nBitte Zaehler vom ersten Bruch eingeben: ");
    scanf_s("%i", &zaehler1);
    do {
        printf("\nBitte den Nenner vom ersten Bruch eingeben: ");
        scanf_s("%i", &nenner1);
        if (nenner1 != 0) {
            break;
        }
        printf("\nNenner darf nicht 0 sein!");
    } while (nenner1 == 0);

    printf("\nBitte den Zaehler vom zweiten Bruch eingeben: ");
    scanf_s("%i", &zaehler2);
  
 do {
        printf("\nBitte den Nenner vom zweiten Bruch eingeben: ");
        scanf_s("%i", &nenner2);
      
        if (nenner2 != 0) {
            break;
        }
        printf("\nNenner darf nicht 0 sein!");
    } while (nenner2 == 0);

    printf("\nBitte Rechenzeichen waehlen (1 = +   2 = -   3 = *   4 = /) :");
    scanf_s("%i", &zahl);

    if (zahl == 1) {
        if (nenner1 == nenner2) {
            printf("\n %i|%i + %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, zaehler1 + zaehler2, nenner1);
        }
  
        else {
            int zaehler3 = zaehler1 * nenner2;
            int nenner3 = zaehler2 * nenner1;
            int ergebniszaehler = zaehler3 + nenner3;
            int *zeiger;
            zeiger = &nenner1;
            int *zeiger2;
            zeiger2 = &nenner2;
            int *zeiger3;
            zeiger3 = &ergebniszaehler;
            int *zeiger4;
            zeiger4 = &kgv;
            int p = nenner1;
            int q = nenner2;
            while (q != 0) {
                r = p % q;
                p = q;
                q = r;
            }
          
            kgv = (*zeiger * *zeiger2) / p;
          
            printf("\n Ergebnis %i|%i + %i|%i = %i|%i + %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, zaehler3, kgv, nenner3, kgv, ergebniszaehler, kgv);
            int x = ergebniszaehler;
            int y = kgv;
            while (y != 0) {
                r = x % y;
                x = y;
                y = r;
            }
            printf("\n Gekuertzt ist der Bruch %i|%i", *zeiger3 / x, *zeiger4 / x);
        }
    }

    if (zahl == 2) {
        if (nenner1 == nenner2) {
            printf("\n %i|%i - %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, zaehler1 - zaehler2, nenner1);
        }
        else {
            int zaehler3 = zaehler1 * nenner2;
            int nenner3 = zaehler2 * nenner1;
            int ergebniszaehler = zaehler3 - nenner3;
            int *zeiger;
            zeiger = &nenner1;
            int *zeiger2;
            zeiger2 = &nenner2;
            int *zeiger3;
            zeiger3 = &ergebniszaehler;
            int *zeiger4;
            zeiger4 = &kgv;
            int p = nenner1;
            int q = nenner2;
            while (q != 0) {
                r = p % q;
                p = q;
                q = r;
            }
            kgv = (*zeiger * *zeiger2) / p;
            printf("\n Ergebnis %i|%i - %i|%i = %i|%i - %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, zaehler3, kgv, nenner3, kgv, ergebniszaehler, kgv);
            int x = ergebniszaehler;
            int y = kgv;
            while (y != 0) {
                r = x % y;
                x = y;
                y = r;
            }
            printf("\n Gekuertzt ist der Bruch %i|%i", *zeiger3 / x, *zeiger4 / x);
        }
    }
        if (zahl == 3) {
            int ergebnis1 = zaehler1 * zaehler2;
            int ergebnis2 = nenner1 * nenner2;
            int *zeiger;
            zeiger = &ergebnis1;
            int *zeiger2;
            zeiger2 = &ergebnis2;
            printf("\n %i|%i * %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, ergebnis1, ergebnis2);
            int p = ergebnis1;
            int q = ergebnis2;
            while (q != 0) {
                r = p % q;
                p = q;
                q = r;
            }
            printf("\n Gekuertzt ist der Bruch %i|%i", *zeiger / p, *zeiger2 / p);
        }
        if (zahl == 4) {
            int ergebnis1 = zaehler1 * nenner2;
            int ergebnis2 = zaehler2 * nenner1;
            int *zeiger;
            zeiger = &ergebnis1;
            int *zeiger2;
            zeiger2 = &ergebnis2;
            printf("\n %i|%i / %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, ergebnis1, ergebnis2);
            int p = ergebnis1;
            int q = ergebnis2;
            while (q != 0) {
                r = p % q;
                p = q;
                q = r;
            }
            printf("\n Gekuertzt ist der Bruch %i|%i", *zeiger / p, *zeiger2 / p);
        }
        goto marker;
    }
 
Zuletzt bearbeitet von einem Moderator:

cwriter

Erfahrenes Mitglied
Folgendes Problem, wenn man einen Bruch eingibt erkennt er nicht, dass nur ein Bruch berechnet werden muss und nicht beide.
"Bruch berechnen" ist was genau?
Meinst du, wenn die Nenner nicht teilerfremd sind?
Das ist eine ziemlich schlechte Optimierung; der Computer rechnet dir auch gerne mehr, aber im Prinzip würde ja ein n1 % n2 == 0 || n2 % n1 == 0 zur Überprüfung reichen. Der Quotient ist dann der Multiplikator für den einen Zähler. Meintest du das?

Sonst wäre ich, glaube ich, soweit fertig. Evtl könnte man es ein bisschen besser umschreiben.
Ehrlich gesagt hilft da eher Brandrodung. Der Code ist absolut unleserlich.
(Mit den Codetags [code=c][/code] sähe es wohl ein bisschen besser aus, aber nicht viel...)

Das Kürzen der Brüche tust du ja mehrmals, warum nicht als Funktion? Und warum kreierst du Zeiger, die du dann eh nicht brauchst?

Gruss
cwriter
 

Scooopy

Grünschnabel
Hallo cwriter,

Danke dir schon mal für das Feedback.

Also wir sollen einen Programm zum berechnen von Brücken schreiben.
Bei Addition und Subtraktion brauchen ich den selben Nenner, sprich kgV.


Bin ziemlicher Neuling..
In wie gern meinst du mit einer Funktion?
 

cwriter

Erfahrenes Mitglied
Bei Addition und Subtraktion brauchen ich den selben Nenner, sprich kgV.
Nein, ihr braucht den gleichen Nenner. Dieser muss nicht kgV sein. Das kgV zu bestimmen ist viel aufwendiger als eine einfache Multiplikation.

In wie gern meinst du mit einer Funktion?
Du kannst den ggT-Algorithmus in einen Funktion auslagern, um es übersichtlicher zu gestalten. Was eine Funktion ist: Bitte suchen, da findet sich genug.

Gruss
cwriter
 

cwriter

Erfahrenes Mitglied
Wie gesagt: Du brauchst nicht das kleinste gemeinsame Vielfache, sondern irgendein gemeinsames Vielfaches.
Durch Multiplizieren mit dem jeweils anderen Nenner bekommst du ein gemeinsames Vielfaches, aber nicht immer das kleinste. Z.B. ist kgV(4,8) = 8, aber 4*8=32.
Für eine Rechnung 1/4 + 1/8 ist es aber irrelevant, ob es 2/8 +1/8 = 3/8 oder 8/32 + 4/32 = 12/32 = 6/16 = 3/8 ist.

Für Computer geht eine Multiplikation schneller als ein Algorithmus für das kgV. Der einzige Nachteil der Multiplikation ist, dass der Wertebereich schneller erschöpft ist (Over-/Underflows treten schneller auf).

Gruss
cwriter
 

Scooopy

Grünschnabel
Hallo cwriter,

ich hab das ganze jetzt noch mal mit einer Funktion gemacht, gibt es sonst noch etwas was ich besser machen könnte?

C:
#include <stdio.h>
int ggt(int p, int q) {
    int r;
    while (q != 0) {
        r = p % q;
        p = q;
        q = r;
    }
    return p;
}
main() {
    int zaehler1, zaehler2, nenner1, nenner2, zahl;
marker:;
    //Die Eingabe des Zählers des ersten Bruchs
    printf("\nBitte Zaehler vom ersten Bruch eingeben: ");
    scanf_s("%i", &zaehler1);
    //Die Eingabe des Nenners des ersten Bruchs
    do {
        printf("\nBitte den Nenner vom ersten Bruch eingeben: ");
        scanf_s("%i", &nenner1);
        if (nenner1 != 0) {
            break;
        }
        printf("\nNenner darf nicht 0 sein!");
    } while (nenner1 == 0);
    //Die Eingabe des Zählers des zweiten Bruchs
    printf("\nBitte den Zaehler vom zweiten Bruch eingeben: ");
    scanf_s("%i", &zaehler2);
    //Die Eingabe des Nenners des zweiten Bruchs
    do {
        printf("\nBitte den Nenner vom zweiten Bruch eingeben: ");
        scanf_s("%i", &nenner2);
        if (nenner2 != 0) {
            break;
        }
        printf("\nNenner darf nicht 0 sein!");
    } while (nenner2 == 0);
    // Die Wahl des Rechenzeichens
    printf("\nBitte Rechenzeichen waehlen (1 = +   2 = -   3 = *   4 = /) : ");
    scanf_s("%i", &zahl);
    // Berechnung falls die Nenner gleich sind
    if (zahl == 1) {
        if (nenner1 == nenner2) {
            int zaehler3 = zaehler1 + zaehler2;
            printf("\n %i|%i + %i|%i = %i|%i", zaehler1, nenner1, zaehler2, nenner2, zaehler3, nenner1);
            int t = ggt(zaehler3, nenner1);
            zaehler3 = zaehler3 / t;
            nenner1 = nenner1 / t;
            //printf("\nGGT: %i \n", t);
            printf("\n Gekuerzt ist der Bruch: %i / %i\n", zaehler3, nenner1);
        }
        //Berechnung falls die Nenner nicht gleich sind
        else {
            int zaehler3 = zaehler1 * nenner2;
            int zaehler4 = zaehler2 * nenner1;
            int ergebnisnenner = nenner1 * nenner2;
            int ergebniszaehler = zaehler3 + zaehler4;
            printf("\n %i|%i + %i|%i = %i|%i + %i|%i = %i|%i\n", zaehler1, nenner1, zaehler2, nenner2, zaehler3, ergebnisnenner, zaehler4, ergebnisnenner, ergebniszaehler, ergebnisnenner);
            int t = ggt(ergebniszaehler, ergebnisnenner);
            ergebniszaehler = ergebniszaehler / t;
            ergebnisnenner = ergebnisnenner / t;
            //printf("\nGGT: %i \n", t);
            printf("\n Gekuerzt ist der Bruch: %i / %i\n", ergebniszaehler, ergebnisnenner);
        }
    }
    // Berechnung falls die Nenner gleich sind
    if (zahl == 2) {
        if (nenner1 == nenner2) {
            int zaehler3 = zaehler1 - zaehler2;
            printf("\n %i|%i - %i|%i = %i|%i\n", zaehler1, nenner1, zaehler2, nenner2, zaehler3, nenner1);
            int t = ggt(zaehler3, nenner1);
            zaehler3 = zaehler3 / t;
            nenner1 = nenner1 / t;
            //printf("\nGGT: %i \n", t);
            printf("\n Gekuerzt ist der Bruch: %i / %i\n", zaehler3, nenner1);
        }
        //Berechnung falls die Nenner nicht gleich sind
        else {
            int zaehler3 = zaehler1 * nenner2;
            int zaehler4 = zaehler2 * nenner1;
            int ergebnisnenner = nenner1 * nenner2;
            int ergebniszaehler = zaehler3 - zaehler4;
            printf("\n %i|%i - %i|%i = %i|%i - %i|%i = %i|%i\n", zaehler1, nenner1, zaehler2, nenner2, zaehler3, ergebnisnenner, zaehler4, ergebnisnenner, zaehler3 - zaehler4, ergebnisnenner);
            int t = ggt(ergebniszaehler, ergebnisnenner);
            ergebniszaehler = ergebniszaehler / t;
            ergebnisnenner = ergebnisnenner / t;
            //printf("\nGGT: %i \n", t);
            printf("\n Gekuerzt ist der Bruch: %i / %i\n", ergebniszaehler, ergebnisnenner);
        }
    }
  
    if (zahl == 3) {
    int ergebniszaehler = zaehler1 * zaehler2;
    int ergebnisnenner = nenner1 * nenner2;
  
    printf("\n %i|%i * %i|%i = %i|%i\n", zaehler1, nenner1, zaehler2, nenner2, ergebniszaehler, ergebnisnenner);
    int t = ggt(ergebniszaehler, ergebnisnenner);
    ergebniszaehler = ergebniszaehler / t;
    ergebnisnenner = ergebnisnenner / t;
    //printf("\nGGT: %i \n", t);
    printf("\n Gekuerzt ist der Bruch: %i / %i\n", ergebniszaehler, ergebnisnenner);
    }
    if (zahl == 4) {
    int ergebniszaehler = zaehler1 * nenner2;
    int ergebnisnenner = zaehler2 * nenner1;
  
    printf("\n %i|%i / %i|%i = %i|%i\n", zaehler1, nenner1, zaehler2, nenner2, ergebniszaehler, ergebnisnenner);
    int p = ergebniszaehler;
    int q = ergebnisnenner;
    int t = ggt(ergebniszaehler, ergebnisnenner);
    ergebniszaehler = ergebniszaehler / t;
    ergebnisnenner = ergebnisnenner / t;
    //printf("\nGGT: %i \n", t);
    printf("\n Gekuerzt ist der Bruch: %i / %i\n", ergebniszaehler, ergebnisnenner);
    }
  
    goto marker;
}
 
Zuletzt bearbeitet von einem Moderator:

ComFreek

Mod | @comfreek
Moderator
Ein paar Vorschläge:

- Code-Tags nutzen! Ich habe dies für dich schon zwei Mal gemacht, beim dritten Mal schaffst du es bitte selbst ;)
- Deine ggt-Funktion static deklarieren.
- Einzelne Berechnungen auch in Funktionen auslagern.
- Deine Nutzung von goto sollte durch eine while-Schleife ersetzt werden.
- Einrückungen sind teilweise falsch. Du könntest Autoformat deiner IDE nutzen.