A27: rationale Zahlen

A27: rationale Zahlen

Beitragvon Kazaar » 25.06.2010 20:57

Hallo!
Solltet ihr mal versuchen, mit negativen Zahlen zu rechnen und euch wundern, dass es bei eurem Programm nicht klappt (oder nicht ganz richtig), beachtet, dass der Euklidische Algorithmus nur für natürliche (insbesondere heißt das positive) Zahlen (richtig) funktioniert. Wenn ihr mit dem Betrag der eingegebenen Zahlen arbeitet, kommt das Richtige heraus. Und im Wikipedia-Artikel steht die heute übliche Form des Algorithmus erst im zweiten Abschnitt, die davor ist etwas veraltet... ;)

Und wo ich schon schreibe, biete ich mal meinen Code an. Vielleicht hilft er irgendwem.

Code: Alles auswählen
/*
* source.cpp
*
*  Created on: 25.06.2010
*      Author: Kazaar
*       Title: Aufgabe 27
*/

#include <iostream>
#include <cmath>

using namespace std;

// Freie Funktion
long ggT(long, long);

// Klasse
class bruch {
private:
   long oben, unten;
   void vorzeichen_kontrollieren(); // auf ein Objekt selbst anwendbar

public:
   // Konstruktur mit Standardwerten, die bei Bedarf eingefüllt werden
   bruch(long a = 0, long b = 1) {
      oben = a;
      unten = b;
      kuerzen();
   }

   // Kürzen
   void kuerzen();

   // Rechenoperationen mit Operatoren
   bruch operator+(bruch);
   bruch operator-(bruch);
   bruch operator*(bruch);
   bruch operator/(bruch);

   // negatives Vorzeichen, d.h. unärer Operator
   bruch operator-();

   // Ausgabe
   double kommazahl();
   friend ostream & operator<<(ostream &, bruch);
};

// Vorzeichen kontrollieren in Methoden, wird auf Objekt selbst angewendet
void bruch::vorzeichen_kontrollieren() {
   // Der Bruch darf ein negatives Vorzeichen nur im Zähler haben.
   if (oben * unten > 0) { // Zähler und Nenner beide positiv oder negativ
      oben = abs(oben);
      unten = abs(unten);
   }
   else {
      oben = - abs(oben);
      unten = abs(unten);
   }
}

void bruch::kuerzen() {
   vorzeichen_kontrollieren();
   long c = ggT(oben, unten);
   oben = oben / c;
   unten = unten / c;
}

bruch bruch::operator+(bruch zwei) {
   bruch ausgabe;
   ausgabe.oben = oben * zwei.unten + zwei.oben * unten;
   ausgabe.unten = unten * zwei.unten;
   ausgabe.kuerzen();
   return ausgabe;
}

bruch bruch::operator-(bruch zwei) {
   bruch ausgabe;
   ausgabe.oben = oben * zwei.unten - zwei.oben * unten;
   ausgabe.unten = unten * zwei.unten;
   ausgabe.kuerzen();
   return ausgabe;
}

bruch bruch::operator*(bruch zwei) {
   bruch ausgabe;
   ausgabe.oben = oben * zwei.oben;
   ausgabe.unten = unten * zwei.unten;
   ausgabe.kuerzen();
   return ausgabe;
}

bruch bruch::operator/(bruch zwei) {
   bruch ausgabe;
   ausgabe.oben = oben * zwei.unten;
   ausgabe.unten = unten * zwei.oben;
   ausgabe.kuerzen();
   return ausgabe;
}

bruch bruch::operator-() {
   // nicht das eigene Objekt (Instanz) ändern, sondern Objekt mit negativem Wert zurückgeben!
   bruch c;
   c.oben = oben;
   c.unten = unten;
   kuerzen();
   c.oben = - c.oben;
   return c;
}

double bruch::kommazahl() {
   return double(oben) / double(unten); // ohne Umwandlung Ganzzahldivision!
}

ostream & operator<<(ostream & str, bruch eingabe) {
   str << eingabe.oben << "/" << eingabe.unten;
   return str;
}

long ggT(long a, long b) {
   // größter gemeisamer Teiler nach Euklidischem Algorithmus von Wikipedia
   a = abs(a);
   b = abs(b);
   long h;
   while (b != 0) {
      h = a % b;
      a = b;
      b = h;
   }
   return a;
}

// ----------------- main ----------------------------------------------
int main () {
   bruch eins(2, 25), zwei(7, 5), drei(2, 5), vier(1, 4), fuenf(1, 3);
   bruch ergebnis = eins / zwei - drei * (-vier + fuenf);
   cout << "Ergebnis = " << ergebnis << " = " << ergebnis.kommazahl() << endl;

   cout << endl << "-- Beendet --" << endl;
   return 0;
}
Kazaar
 
Beiträge: 326
Registriert: 29.10.2008 21:35

Re: A27: rationale Zahlen

Beitragvon PhoeniX » 27.06.2010 16:03

Hi Leute,
ich habe ein kleines Problem mit meinem ratio-Programm:
Aus irgendeinem Grund initialistert mein Konstrultor nur Brüche mit den Default-Werten und ignoriert semtliche anderen eingaben.
Am besten mal ausprobieren mit einem bsp. (addition geht schon, noch oihne kürzen). Es werden als ergebnis immer die standardwerte angezeigt.

Schon mal viele Dank an jeden, der sich damit befasst,
lg
PhoeniX

Code: Alles auswählen
#include <cstdlib>
#include <iostream>

using namespace std;

// 1. Deklaration der Klasse ratio
class ratio
{
     
private:
      double zaehler;
      double nenner;

public:
     
      ratio (double z=0.0, double n=0.0){; // Deklaration und SOFORT definition eines konstruktors
            zaehler=z;
            nenner=n;}

      double ggt(double, double); // groesster gemeinsamer teiler
     
      ratio operator + (ratio);
      ratio operator - (ratio);
      ratio operator * (ratio);
      ratio operator / (ratio);
     
      friend ostream &operator<< (ostream &, ratio);
      friend istream &operator>> (istream &, ratio);
};

// 2. Definition der Methoden der Klasse ratio
// 2.1 Defintion des Konstruktors:
// ACHTUNG: der konstruktor muss bereits beim ersten aufruf, d.h. bei der deklaration definiert werden!

// 2.2 Definition des Operators +
ratio ratio::operator+ (ratio b){
      ratio c;
      c.zaehler=(zaehler*b.nenner)+(b.zaehler*nenner);
      c.nenner=nenner*b.nenner;
      return c;
      }

// 2.3 Definition des Operators -
ratio ratio::operator- (ratio b){
      ratio c;
      c.zaehler=(zaehler*b.nenner)+(b.zaehler*nenner);
      c.nenner=nenner*b.nenner;
      return c;
      }

// 2.4 Definition des Operators *
ratio ratio::operator* (ratio b){
      ratio c;
      c.zaehler=zaehler*b.zaehler;
      c.nenner=nenner*b.nenner;
      return c;
      }

// 2.5 Definition des Operators /
ratio ratio::operator/ (ratio b){
      ratio c;
      c.zaehler=zaehler*b.nenner;
      c.nenner=nenner*b.zaehler;
      return c;
      }

// 2.6 Definition des groessten gemeinsamen Teilers:
double ratio::ggt (double b, double c){
 
     if (b<1){b=-b;}
     
     if (c<1){c=-c;}
                   
     if (b>c){
              return (ggt(b-c, c));}
                           
     if (c>b){
              return (ggt(b, c-b));}
     
     double d=b; // b ist ggt nach rekursion! deshalb wird d als b gesetzt!
     cout << "Der ggt ist " << d << endl;
     return d;
}

// 2.7 Definition der Ausgabe ueber <<Operator (vgl. Vorlesung 11)
ostream &operator<< (ostream &str, ratio z){
    str << "Ergebnis: " << z.zaehler << " / " << z.nenner;
    return str;
}

//2.8 Definition der Eingabe ueber >>Operator (vgl. Vorlesung 11)
istream &operator>> (istream &is, ratio z){
        is >> z.zaehler >> z.nenner;
        return is;
}


//3. main-Programm:
     
int main(){
    cout << "Willkommen zum Bruchrechen-Programm" << endl;
    cout << " Bitte waehlenb Sie die Rechenart aus: " << endl << endl;
    cout << "1) Addieren" << endl << "2) Subtrahieren" << endl << "3) Multiplizieren" << endl << "4) Dividieren" << endl << endl;
   
    int a;
    cin >> a;
    cout << endl << endl;
   
//3.1 Addition:
    if (a==1){
              ratio a, b,c;
              double d;
             
              cout << "Bitte die beiden Brueche eingeben." << endl;
              cout << "erster Bruch: " << endl;
              cin >> a;
             
              cout << "zweiter Bruch: " << endl;
              cin >> b;
             
              c=a+b;
             
              cout << c << endl;
              }
             
   
   
   
    system("PAUSE");
    return EXIT_SUCCESS;
}


PhoeniX
 
Beiträge: 23
Registriert: 06.05.2009 19:18

Re: A27: rationale Zahlen

Beitragvon Mammutbaum » 28.06.2010 10:08

Dein Fehler liegt hier:

ratio (double z=0.0, double n=0.0) {...}

du überschreibst die übergebenen Werte hier permanent wieder mit 0, mach das raus und schreib einfach mal

ratio (double z, double n) {...}

hin.... zusätzlich kannst du dann auch noch nen Konstruktor mit

ratio () {....}

definieren, der dir dann vordefinierte Werte einsetzt, sofern du das möchtest.
Mammutbaum
 
Beiträge: 18
Registriert: 12.11.2008 19:35

Re: A27: rationale Zahlen

Beitragvon Cashdogg » 28.06.2010 14:32

Und beim Minus-Operator muss bei der Dekleration ein - anstelle eines +.
Cashdogg
 
Beiträge: 408
Registriert: 20.12.2008 15:05

Re: A27: rationale Zahlen

Beitragvon PhoeniX » 28.06.2010 15:21

Hey Leute,
vielen Dank für Eure schnelle Hilfe. Ich probiere es gleich mal aus.
mfg
PhoeniX
PhoeniX
 
Beiträge: 23
Registriert: 06.05.2009 19:18

Re: A27: rationale Zahlen

Beitragvon Cashdogg » 28.06.2010 15:36

Hmm, mein unärer Operator schein nicht richtig zu funktionieren. Hat da jemand eine Idee?

Code: Alles auswählen
//Deklariere den unären --Opeators

Ratio Ratio::operator-()
{
   Ratio c;
   c.Zaehler*=-1;
   c.Nenner=Nenner;
   c.Kuerzen();
   return c;
}


Ich poste doch mal besser alles:

Code: Alles auswählen
/* Programmieren für Physiker - SS2010 - Übungsblatt 11 - Aufgabe 27 */

#include <iostream>

using namespace std;

//Dekleration der Klasse

class Ratio
{
private:
   double Zaehler;
   double Nenner;
   void Kuerzen();
public:
   Ratio (int a=0, int b=1)
   {Zaehler=a; Nenner=b; };
   void Setze (int z, int n);
   Ratio operator+(Ratio Wert);
   Ratio operator-(Ratio Wert);
   Ratio operator-();
   Ratio operator*(Ratio Wert);
   Ratio operator/(Ratio Wert);
   double Gleitkomma();

   friend ostream& operator<< (ostream &, Ratio); 
};

//Deklariere Methode zum Setzen der Variablen

void Ratio::Setze (int z, int n)
{
    Zaehler=z;
    Nenner=n;
   Kuerzen();
}

//Bestimme größten gemeinsamen Teiler mittels des rekursiven euklidischen Algorithmuses

int EUKLID(int a, int b)
{
   if (b==0)
      return a;
   else
   return EUKLID(b, a%b);
}

//Deklariere Methode zum Kürzen und zur Vorzeichenkorrektur

void Ratio::Kuerzen()
{
   if (Nenner < 0)
   {
      Zaehler*=-1;
      Nenner*=-1;
   }

   int x=EUKLID (Zaehler, Nenner);
   Nenner=Nenner/x;
   Zaehler=Zaehler/x;
}

//Deklariere den +-Opeators

Ratio Ratio::operator+(Ratio Wert)
{
   Ratio c;
   c.Zaehler=(Zaehler*Wert.Nenner)+(Nenner*Wert.Zaehler);
   c.Nenner=Nenner*Wert.Nenner;
   c.Kuerzen();
   return c;
}

//Deklariere den --Opeators

Ratio Ratio::operator-(Ratio Wert)
{
   Ratio c;
   c.Zaehler=(Zaehler*Wert.Nenner)-(Nenner*Wert.Zaehler);
   c.Nenner=Nenner*Wert.Nenner;
   c.Kuerzen();
   return c;
}

//Deklariere den unären --Opeators

Ratio Ratio::operator-()
{
   Ratio c;
   c.Zaehler*=-1;
   c.Nenner=Nenner;
   c.Kuerzen();
   return c;
}

//Deklariere den *-Opeators

Ratio Ratio::operator*(Ratio Wert)
{
   Ratio c;
   c.Zaehler=Zaehler*Wert.Zaehler;
   c.Nenner=Nenner*Wert.Nenner;
   c.Kuerzen();
   return c;
}

//Deklariere den /-Opeators

Ratio Ratio::operator/(Ratio Wert)
{
   Ratio c;
   c.Zaehler=Zaehler*Wert.Nenner;
   c.Nenner=Nenner*Wert.Zaehler;
   c.Kuerzen();
   return c;
}

//Deklariere die Methode zur Umwandlung in Gleitkommazahl

double Ratio::Gleitkomma()
{
   double c=(double (Zaehler))/(double (Nenner));
   return c;
}

//Deklarier "Ausgabefreund" (vgl. Übungsbeispiel complex-class.cc)

ostream& operator<< (ostream & Ausgabe, Ratio c)
{
    Ausgabe << "x/y = " << c.Zaehler << "/" << c.Nenner;
    return Ausgabe;
}

// Hautprogramm (Ein- und Ausgabe)

int main()
{
   Ratio a(2,25);
    Ratio b(7,5);
    Ratio c(2,5);
    Ratio d(1,4);
    Ratio e(1,3);
   
   Ratio Loesung = a/b-c*(-d+e);
   
   cout << "==============Programm zur Berechnung rationaler Rechenoperationen==============" << endl;
   cout << endl;
   cout << "Ergebnis als Bruch: " << Loesung << endl;
   cout << endl;
    cout << "Ergebnis als double: " << Loesung.Gleitkomma() << endl;
   cout << endl;
}
Cashdogg
 
Beiträge: 408
Registriert: 20.12.2008 15:05

Re: A27: rationale Zahlen

Beitragvon M.A. » 28.06.2010 16:13

Cashdogg hat geschrieben:Hmm, mein unärer Operator schein nicht richtig zu funktionieren. Hat da jemand eine Idee?

Code: Alles auswählen
//Deklariere den unären --Opeators

Ratio Ratio::operator-()
{
   Ratio c;
   c.Zaehler*=-1;
   c.Nenner=Nenner;
   c.Kuerzen();
   return c;
}

Wie wäre es mit
Code: Alles auswählen
//Deklariere den unären --Opeators

Ratio Ratio::operator-()
{
   Ratio c;
   c.Zaehler=-Zaehler;
   c.Nenner=Nenner;
   c.Kuerzen();
   return c;
}
Bild
Benutzeravatar
M.A.
 
Beiträge: 366
Registriert: 25.10.2008 16:37

Re: A27: rationale Zahlen

Beitragvon Cashdogg » 28.06.2010 16:57

Geht tatsächlich. Danke. Ist aber ...*=-1 nicht gleich ...=-Zaehler?!
Cashdogg
 
Beiträge: 408
Registriert: 20.12.2008 15:05

Re: A27: rationale Zahlen

Beitragvon Holger » 28.06.2010 21:39

Dein c.Zaehler ist vorher nicht mit dem richtigen Wert initialisiert worden, also ist c.Zaehler*=-1 nicht zielführend.
Holger
 
Beiträge: 56
Registriert: 13.11.2008 21:21


Zurück zu Programmieren

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

cron