DESCRIPTION
Hello,
Fractions are defined here with 64-bit integers.
We make sure that the denominator is always positive.
Special case: indefinite fraction ↔ denominator = 0.
Division-by-zero errors are handled, but beware: no overflow-time overflow checking!
Functions developed (with A, B: fractions; N, D, I: integers):
Manufacturer (with simplification):
Frac (N, D)
Unary operations:
+ A, -A
Assignments:
+ = B, – = B, * = B, / = B
Arithmetic operations:
A + B, A – B, A * B, A / B
A + I, A – I, A * I, A / I
I + A, I – A, I * A, I / A
The simple struct structure is used to facilitate the transcription of code in other programming languages:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #define llint long long int struct Frac { llint num, den; // den> = 0; indefinite: den = 0; Frac() {num = 1; den = 0;} // constructor (indefinite) 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) { // with 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;} |
To make it a “library” (library software), it is better to use a structure more “complete”, that is to say with protections.
The tests in Fractions.cpp of the Zip show that we can write combinations of arithmetic operations by mixing integers and fractions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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 |
The Val and Out functions are used to “check” calculations.
The last example is the continuous fraction approaching √2:
1 2 3 4 5 6 7 8 9 | 1 √2 = 1 + ─────────────── 1 2 + ─────────── 1 2 + ─────── 2 + ... |