next up previous contents index
Next: Dettagli sulle classi. Templates Up: Due esempi concreti Previous: Numeri complessi   Indice   Indice analitico

Numeri razionali

Per rappresentare un numero razionale useremo due int, numeratore e denominatore, ed un flag di controllo booleano, il quale indichi se il numero ha significato. Ricordiamo che un numero razionale è definito come il rapporto di due numeri interi, ove il denominatore sia un numero qualunque diverso da zero; per comodità consideremo il denominatore sempre positivo, per cui il segno del numero razionale sarà dato dal segno del numeratore. Le operazioni di somma e sottrazione sono volutamente non ottimizzate, in maniera tale da mostrare un codice più leggibile ed intuitivo. Come nel caso della classe Complesso, anche per la classe Razionale distribuiremo il codice in un file di intestazione (razionale.h) e in un file contenente le definizioni delle funzioni troppo elaborate per essere definite all'interno della dichiarazione di classe (razionale.cpp); inoltre forniremo in coda un esempio di utilizzo della classe.

Si noti che anche in questo caso, siccome i campi dati della classe Razionale sono tutti non dinamici, si utilizzeranno il costruttore di copia, l'operatore di assegnamento e il distruttore default.


// razionale.h
// classe rappresentante un numero razionale

#include <iostream.h>
#include <math.h>

class Razionale {
public:
  Razionale (int Num = 0, int Den = 1);
  // Razionale (const Razionale&);
  // const Razionale& opetator= (const Razionale&);
  // ~Razionale();

  // funzioni di accesso
  int numeratore() const {
    if (valido) return num; else return 0; }
  int denominatore() const {
    if (valido) return den; else return 0; }
  bool numeroValido() const { return valido; }
  int segno() const;
  void stampa() const;

  // operatori aritmetici
  Razionale operator- () const {     // meno unario!
    if (valido == false) return Razionale(1,0);
    else return Razionale (-num, den); }
  Razionale operator+ (Razionale b) const;
  Razionale operator- (Razionale b) const {
    return *this + (-b); }
  Razionale operator* (Razionale b) const {
    return Razionale (num * b.num, den * b.den); }
  Razionale operator/ (Razionale b) const {
    return Razionale (num * b.den, den * b.num); }

  // operatori aritmetici & assegnamento
  Razionale& operator+= (Razionale b);
  Razionale& operator-= (Razionale b) {
    return (*this += -b); }
  Razionale& operator*= (Razionale b);
  Razionale& operator/= (Razionale b);
  Razionale& operator++ (int) {
    return (*this += 1); }
  Razionale& operator-- (int) {
    return (*this -= 1); }

  // operatori di confronto
  bool operator<  (Razionale b) const;
  bool operator== (Razionale b) const;
  bool operator<= (Razionale b) const{
    return (*this < b) || (*this == b); }
  bool operator!= (Razionale b) const {
    return !(*this == b); }
  bool operator>  (Razionale b) const {
    return !(*this <= b); }
  bool operator>= (Razionale b) const{
    return !(*this > b); }
private:
  int num, den; // numeratore & denominatore
  bool valido;  // flag: numero valido     -> true
                //       numero non valido -> false
  // funzioni per uso interno alla classe
  int max() const {  // restituisce il maggiore tra num e den
    int Num = num * segno();  // Num e` positivo
    if (Num >= den) return Num; else return den; }
  int min() const {
    int Num = num * segno();  // Num e` positivo
    if (Num <= den) return Num; else return den; }
  void semplifica();
  int mcd (int a, int b) const;
  int mcm (int a, int b) const {
    int m = (a * b) / mcd(a,b);
    return abs(m); }
};

// overloading della funzione pow della libreria `math.h'
Razionale pow (Razionale base, int esponente);
double pow (Razionale base, double esponente);

// razionale.cpp

#include "razionale.h"

Razionale::Razionale (int Num, int Den) {
  if (Den != 0) {
    // den deve essere positivo
    if (Den > 0)
      den = Den;
    else
      den = -Den;
    num = Num;
    valido = true;
    semplifica();
  }
  else
    valido = false;  // denominatore nullo
}

void Razionale::stampa() const {
  if (valido == false)
    cout << "nan"; // Not A Number: numero non valido
  else
    cout << num << '/' << den;
}

int Razionale::segno() const {
  if (num == 0)
    return 0;
  else if (num > 0)
    return 1;
  else
    return -1;
}

void Razionale::semplifica () {
  if (valido) {
    if (num != 0) {
      int m = mcd (num, den);
      num /= m;
      den /= m;
    }
    else
      den = 1;
  }
}

int Razionale::mcd (int a, int b) const {
  a = abs(a); b = abs(b);
  while (a != b)
    if (a > b)
      a -= b;
    else
      b -= a;
  return a;
}

Razionale Razionale::operator+ (Razionale b) const {
  if (valido == false || b.valido == false)
    return Razionale (1,0);
  int den_comune = mcm (den, b.den);
  int num_somma = (den_comune / den) * num +
    (den_comune / b.den) * b.num;
  return Razionale (num_somma, den_comune);
}

Razionale& Razionale::operator+= (Razionale b) {
  if (valido == false || b.valido == false) {
    *this = Razionale (1,0);
    return *this;
  }
  int den_comune = mcm (den, b.den);
  int num_somma = (den_comune / den) * num +
    (den_comune / b.den) * b.num;
  *this = Razionale (num_somma, den_comune);
  return *this;
}

Razionale& Razionale::operator*= (Razionale b) {
  if (valido == false || b.valido == false) {
    *this = Razionale (1,0);
    return *this;
  }
  num *= b.num;
  den *= b.den;
  semplifica();
  return *this;
}

Razionale& Razionale::operator/= (Razionale b) {
  if (valido == false || b.valido == false) {
    *this = Razionale (1,0);
    return *this;
  }
  num *= b.den;
  den *= b.num;
  semplifica();
  return *this;
}

bool Razionale::operator< (Razionale b) const {
  if (valido == false || b.valido == false)
    return false;
  double x = double(num) / double(den);
  double y = double(b.num) / double(b.den);
  if (x < y) return true;
  return false;
}

bool Razionale::operator== (Razionale b) const {
  if (valido == false || b.valido == false)
    return false;
  if (num == b.num && den == b.den)
    return true;
  else
    return false;
}

Razionale pow (Razionale base, int esponente) {
  if (base.numeroValido() == false)
    return Razionale (1,0);
  int num, den;
  if (esponente > 0) {
    num = pow (base.numeratore(), esponente);
    den = pow (base.denominatore(), esponente);
  }
  else if (esponente == 0) {
    num = 0;
    den = 1;
  }
  else { // esponente < 0
    num = pow (base.denominatore(), -esponente);
    den = pow (base.numeratore(), -esponente);
  }
  return Razionale (num, den);
}

double pow (Razionale base, double esponente) {
  if (base.numeroValido() == false)
    return 0;
  double x = double(base.numeratore()) /
    double(base.denominatore());
  return pow(x, esponente);
}

Il programma di esempio è il seguente:


// ex9_7_2
#include "razionale.h"
void main() {
  Razionale a(-5,7), b, c(60,-24), d(42,48), z(6,0);
  cout << "a: "; a.stampa(); cout << "\n";
  cout << "b: "; b.stampa(); cout << "\n";
  cout << "c: "; c.stampa(); cout << "\n";
  cout << "d: "; d.stampa(); cout << "\n";
  cout << "1/0: "; z.stampa(); cout << "\n";
  z = -a;
  cout << "-a: "; z.stampa(); cout << "\n";
  z = a + c;
  cout << "a+c: "; z.stampa(); cout << "\n";
  z = a + 3;
  cout << "a+3: "; z.stampa(); cout << "\n";
  z = a - c;
  cout << "a+c: "; z.stampa(); cout << "\n";
  z = a - 2;
  cout << "a+c: "; z.stampa(); cout << "\n";
  z = a * c;
  cout << "a*c: "; z.stampa(); cout << "\n";
  z = a * 7;
  cout << "a*7: "; z.stampa(); cout << "\n";
  z = a / c;
  cout << "a/c: "; z.stampa(); cout << "\n";
  z = a / 5;
  cout << "a/5: "; z.stampa(); cout << "\n";
  a += d;
  cout << "a+=d: "; a.stampa(); cout << "\n";
  a++;
  cout << "a++: "; a.stampa(); cout << "\n";
  a--;
  cout << "a--: "; a.stampa(); cout << "\n";
  a -= d;
  cout << "a-=d: "; a.stampa(); cout << "\n";
  a *= 3;
  cout << "a*=3: "; a.stampa(); cout << "\n";
  a /= 6;
  cout << "a/=6: "; a.stampa(); cout << "\n";
  z = pow(c, -2);
  cout << "pow(c,-2): "; z.stampa(); cout << "\n";
  double x = pow (c, .5);
  cout << "pow(c,.5): "; cout << x << "\n";
}

output:
a: -5/7
b: 0/1
c: 5/2
d: 7/8
1/0: nan
-a: 5/7
a+c: 25/14
a+3: 16/7
a+c: -45/14
a+c: -19/7
a*c: -25/14
a*7: -5/1
a/c: -2/7
a/5: -1/7
a+=d: 9/56
a++: 65/56
a-: 9/56
a-=d: -5/7
a*=3: -15/7
a/=6: -5/14
pow(c,-2): 4/25
pow(c,.5): 1.58114

Come esercizio si consiglia di scrivere un programma che generi un array di numeri razionali, li ordini in senso crescente e li stampi.


next up previous contents index
Next: Dettagli sulle classi. Templates Up: Due esempi concreti Previous: Numeri complessi   Indice   Indice analitico
Claudio Cicconetti
2000-09-06