Created
February 26, 2019 14:38
-
-
Save bluurn/4ba5cdaa79d94a80ca6e46f9697c3461 to your computer and use it in GitHub Desktop.
CPP: Implementation of Rational
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <sstream> | |
#include <cmath> | |
#include <map> | |
#include <vector> | |
#include <set> | |
using namespace std; | |
class Rational { | |
public: | |
Rational() { | |
numerator = 0; | |
denominator = 1; | |
} | |
Rational(int numerator, int denominator) { | |
int gcd_modulo = gcd(abs(numerator), abs(denominator)); | |
if (numerator != 0) { | |
if (denominator > 0) { | |
this->numerator = numerator / gcd_modulo; | |
this->denominator = denominator / gcd_modulo; | |
} else { | |
this->numerator = -(numerator / gcd_modulo); | |
this->denominator = -(denominator / gcd_modulo); | |
} | |
} else { | |
this->numerator = numerator; | |
this->denominator = 1; | |
} | |
} | |
int Numerator() const { | |
return numerator; | |
} | |
int Denominator() const { | |
return denominator; | |
} | |
private: | |
int gcd(int a, int b) { | |
while (a > 0 && b > 0) { | |
if (a > b) { | |
a %= b; | |
} else { | |
b %= a; | |
} | |
} | |
return a + b; | |
} | |
signed int numerator; | |
int denominator; | |
}; | |
bool operator==(const Rational &lhs, const Rational &rhs) { | |
return lhs.Numerator() == rhs.Numerator() && lhs.Denominator() == rhs.Denominator(); | |
} | |
bool operator<(const Rational &lhs, const Rational &rhs) { | |
return lhs.Numerator() * rhs.Denominator() < rhs.Numerator() * lhs.Denominator(); | |
} | |
Rational operator+(const Rational &lhs, const Rational &rhs) { | |
return { | |
lhs.Numerator() * rhs.Denominator() + rhs.Numerator() * lhs.Denominator(), | |
lhs.Denominator() * rhs.Denominator() | |
}; | |
} | |
Rational operator-(const Rational &lhs, const Rational &rhs) { | |
return { | |
lhs.Numerator() * rhs.Denominator() - rhs.Numerator() * lhs.Denominator(), | |
lhs.Denominator() * rhs.Denominator() | |
}; | |
} | |
Rational operator*(const Rational &lhs, const Rational &rhs) { | |
return { | |
lhs.Numerator() * rhs.Numerator(), | |
lhs.Denominator() * rhs.Denominator() | |
}; | |
} | |
Rational operator/(const Rational &lhs, const Rational &rhs) { | |
return { | |
lhs.Numerator() * rhs.Denominator(), | |
lhs.Denominator() * rhs.Numerator() | |
}; | |
} | |
ostream& operator<<(ostream &stream, const Rational &rational) { | |
stream << rational.Numerator() | |
<< "/" | |
<< rational.Denominator(); | |
return stream; | |
} | |
istream& operator>>(istream& stream, Rational& rational) { | |
if (stream.tellg() == -1) { | |
return stream; | |
} | |
int numerator = 0; | |
int denominator = 1; | |
stream >> numerator; | |
stream.ignore(1); | |
stream >> denominator; | |
Rational new_rational = Rational { numerator, denominator }; | |
rational = new_rational; | |
return stream; | |
} | |
int main() { | |
{ | |
const Rational r(3, 10); | |
if (r.Numerator() != 3 || r.Denominator() != 10) { | |
cout << "Rational(3, 10) != 3/10" << endl; | |
return 1; | |
} | |
} | |
{ | |
const Rational r(8, 12); | |
if (r.Numerator() != 2 || r.Denominator() != 3) { | |
cout << "Rational(8, 12) != 2/3" << endl; | |
return 2; | |
} | |
} | |
{ | |
const Rational r(-4, 6); | |
if (r.Numerator() != -2 || r.Denominator() != 3) { | |
cout << "Rational(-4, 6) != -2/3" << endl; | |
return 3; | |
} | |
} | |
{ | |
const Rational r(4, -6); | |
if (r.Numerator() != -2 || r.Denominator() != 3) { | |
cout << "Rational(4, -6) != -2/3" << endl; | |
return 3; | |
} | |
} | |
{ | |
const Rational r(0, 15); | |
if (r.Numerator() != 0 || r.Denominator() != 1) { | |
cout << "Rational(0, 15) != 0/1" << endl; | |
return 4; | |
} | |
} | |
{ | |
const Rational defaultConstructed; | |
if (defaultConstructed.Numerator() != 0 || defaultConstructed.Denominator() != 1) { | |
cout << "Rational() != 0/1" << endl; | |
return 5; | |
} | |
} | |
{ | |
const Rational r(-6, -8); | |
if (r.Numerator() != 3 || r.Denominator() != 4) { | |
cout << "Rational(-6, -8) != 2/3" << endl; | |
return 6; | |
} | |
} | |
{ | |
Rational r1(4, 6); | |
Rational r2(2, 3); | |
bool equal = r1 == r2; | |
if (!equal) { | |
cout << "4/6 != 2/3" << endl; | |
return 1; | |
} | |
} | |
{ | |
Rational a(2, 3); | |
Rational b(4, 3); | |
Rational c = a + b; | |
bool equal = c == Rational(2, 1); | |
if (!equal) { | |
cout << "2/3 + 4/3 != 2" << endl; | |
return 2; | |
} | |
} | |
{ | |
Rational a(5, 7); | |
Rational b(2, 9); | |
Rational c = a - b; | |
bool equal = c == Rational(31, 63); | |
if (!equal) { | |
cout << "5/7 - 2/9 != 31/63" << endl; | |
return 3; | |
} | |
} | |
{ | |
Rational a(2, 3); | |
Rational b(4, 3); | |
Rational c = a * b; | |
bool equal = c == Rational(8, 9); | |
if (!equal) { | |
cout << "2/3 * 4/3 != 8/9" << endl; | |
return 1; | |
} | |
} | |
{ | |
Rational a(5, 4); | |
Rational b(15, 8); | |
Rational c = a / b; | |
bool equal = c == Rational(2, 3); | |
if (!equal) { | |
cout << "5/4 / 15/8 != 2/3" << endl; | |
return 2; | |
} | |
} | |
{ | |
ostringstream output; | |
output << Rational(-6, 8); | |
if (output.str() != "-3/4") { | |
cout << "Rational(-6, 8) should be written as \"-3/4\"" << endl; | |
return 1; | |
} | |
} | |
{ | |
istringstream input("5/7"); | |
Rational r; | |
input >> r; | |
bool equal = r == Rational(5, 7); | |
if (!equal) { | |
cout << "5/7 is incorrectly read as " << r << endl; | |
return 2; | |
} | |
} | |
{ | |
istringstream input("5/7 10/8"); | |
Rational r1, r2; | |
input >> r1 >> r2; | |
bool correct = r1 == Rational(5, 7) && r2 == Rational(5, 4); | |
if (!correct) { | |
cout << "Multiple values are read incorrectly: " << r1 << " " << r2 << endl; | |
return 3; | |
} | |
input >> r1; | |
input >> r2; | |
correct = r1 == Rational(5, 7) && r2 == Rational(5, 4); | |
if (!correct) { | |
cout << "Read from empty stream shouldn't change arguments: " << r1 << " " << r2 << endl; | |
return 4; | |
} | |
} | |
{ | |
const set<Rational> rs = {{1, 2}, {1, 25}, {3, 4}, {3, 4}, {1, 2}}; | |
if (rs.size() != 3) { | |
cout << "Wrong amount of items in the set" << endl; | |
return 1; | |
} | |
vector<Rational> v; | |
for (auto x : rs) { | |
v.push_back(x); | |
} | |
if (v != vector<Rational>{{1, 25}, {1, 2}, {3, 4}}) { | |
cout << "Rationals comparison works incorrectly" << endl; | |
return 2; | |
} | |
} | |
{ | |
map<Rational, int> count; | |
++count[{1, 2}]; | |
++count[{1, 2}]; | |
++count[{2, 3}]; | |
if (count.size() != 2) { | |
cout << "Wrong amount of items in the map" << endl; | |
return 3; | |
} | |
} | |
cout << "OK" << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment