Calculs avec des fractions

Description

Bonjour,

Les fractions sont définies ici avec des entiers de 64 bits.

On s'arrange pour que le dénominateur soit toujours positif.
Cas particulier: fraction indéfinie ↔ dénominateur = 0.

Les erreurs de division par zéro sont traitées, mais attention: pas celles de débordement (without run-time overflow checking) !

Fonctions développées (avec A, B: fractions; N, D, I: entiers):

Constructeur (avec simplification):
    Frac(N, D)
Opérations unaires:
    +A, -A
Affectations:
    += B, -= B, *= B, /= B
Opérations arithmétiques:
    A + B, A - B, A * B, A / B
    A + I, A - I, A * I, A / I
    I + A, I - A, I * A, I / A

La simple structure struct est utilisée pour faciliter la transcription du code dans d'autres langages de programmation:
#define llint long long int

struct Frac {
  llint num, den; // den >= 0; indéfini: den = 0;

  Frac() {num = 1; den = 0;} // constructor (indéfini)
  Frac(llint n, llint d) {Set(n, d);} // constructor

  Frac& operator += (const Frac& B)
    {Set(num*B.den + den*B.num, den*B.den); return *this;}
  Frac& operator -= (const Frac& B)
    {Set(num*B.den - den*B.num, den*B.den); return *this;}
  Frac& operator *= (const Frac& B)
    {Set(num*B.num, den*B.den); return *this;}
  Frac& operator /= (const Frac& B)
    {Set(num*B.den, den*B.num); return *this;}

  void Set(llint n, llint d) { // avec simplification
    if (d < 0) {n = -n; d = -d;}
    llint r = std::abs(n), s = d, t;
    if (s != 0) { // r = pgcd(r, s)
      do {t = r%s; r = s; s = t;} while (s > 0);
    } else r = 1;
    num = n/r; den = d/r;
  }
};

bool operator == (const Frac& A, const Frac& B)
  {return A.num*B.den == A.den*B.num;}
bool operator != (const Frac& A, const Frac& B)
  {return A.num*B.den != A.den*B.num;}
bool operator < (const Frac& A, const Frac& B)
  {return A.num*B.den < A.den*B.num;}
bool operator > (const Frac& A, const Frac& B)
  {return A.num*B.den > A.den*B.num;}
bool operator <= (const Frac& A, const Frac& B)
  {return A.num*B.den <= A.den*B.num;}
bool operator >= (const Frac& A, const Frac& B)
  {return A.num*B.den >= A.den*B.num;}

Frac operator + (Frac A) {return A;}
Frac operator + (Frac A, const Frac& B) {return A += B;}
Frac operator + (Frac A, llint I) {A.num += I*A.den; return A;}
Frac operator + (llint I, Frac A) {A.num += I*A.den; return A;}
Frac operator - (Frac A) {A.num = -A.num; return A;}
Frac operator - (Frac A, const Frac& B) {return A -= B;}
Frac operator - (Frac A, llint I) {A.num -= A.den*I; return A;}
Frac operator - (llint I, Frac A) {A.num -= I*A.den; return A;}
Frac operator * (Frac A, const Frac& B) {return A *= B;}
Frac operator * (Frac A, llint I) {A.Set(A.num*I, A.den); return A;}
Frac operator * (llint I, Frac A) {A.Set(I*A.num, A.den); return A;}
Frac operator / (Frac A, const Frac& B) {return A /= B;}
Frac operator / (Frac A, llint I) {A.Set(A.num, A.den*I); return A;}
Frac operator / (llint I, Frac A) {A.Set(I*A.den, A.num); return A;}
Pour en faire une "library" (bibliothèque logicielle), il vaut mieux utiliser une structure plus "complète", c'est-à-dire avec des protections.

Les tests dans Fractions.cpp du Zip montrent qu'on peut écrire des combinaisons d'opérations arithmétiques en mélangeant entiers et fractions.
A = Frac(37961, 60639) = [77/123] = 0.626016
B = Frac(460, -2185) = [-4/19] = -0.210526
Frac C; C = [INDEFINI] = inf

+A = [77/123] = 0.626016
-A = [-77/123] = -0.626016
A+B = [971/2337] = 0.41549
A-B = [1955/2337] = 0.836543
A-A = [0/1] = 0

2*A + 7*B = [-518/2337] = -0.221652 =? -0.221652
2*(A-1) - (B+3-A)*5 = [-27028/2337] = -11.5653 =? -11.5653

Fraction continue: C = [5/2] = 2.5
  C = 2 + 1/C = [12/5] = 2.4
  C = 2 + 1/C = [29/12] = 2.41667
  C = 2 + 1/C = [70/29] = 2.41379
  C = 2 + 1/C = [169/70] = 2.41429
  C = 2 + 1/C = [408/169] = 2.4142
  C = 2 + 1/C = [985/408] = 2.41422
  C = 2 + 1/C = [2378/985] = 2.41421
  C = 2 + 1/C = [5741/2378] = 2.41421
  C = 2 + 1/C = [13860/5741] = 2.41421
  C = 2 + 1/C = [33461/13860] = 2.41421
C = 1 + 1/C = [47321/33461] = 1.41421
Les fonctions Val et Out y sont utilisés pour "vérifier" les calculs.

Le dernier exemple correspond à la fraction continue qui s'approche de √2:
                1
√2 = 1 + ───────────────
                  1
         2 + ───────────
                    1
             2 + ───────
                 2 + ...

 
Bonne lecture ...
 

Liens

WikipédiA: Fraction (mathématiques)
WikipédiA: Fraction continue
CodeS-SourceS: Fractions, addition, soustraction, multiplication, division et simplification
GitHub: FractionCPP
GitHub: C++ Rational Number Class
 

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.