Skip to content

Instantly share code, notes, and snippets.

@sklaw
Last active January 27, 2024 07:25
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save sklaw/10473569 to your computer and use it in GitHub Desktop.
Save sklaw/10473569 to your computer and use it in GitHub Desktop.
C++ Rational Number Class
You can use this class in the same way you use "int".
The following operators are available:
+ - * /
++ --
+= -= *= /=
< > <= >= == !=
<< >>
For example:
RationalNum a, b;
a = 5;
b = a + 7;
cin >> a;
cout << a;
b = 0.75;
cout << b;
if (a == 5) {
a++;
}
Output format:
1.When the denominator is 1, it won't be output by default.
For example:
RationalNum a = 7;
cout << a;
these statements will output "1".
2.When the denominator is not 1, it will be output in "int/int" format.
For example:
RationalNum a = 0.25;
cout << a;
these statements will output "1/4".
Input format:
1.you can input a fractional number.
For example: 1.15 -0.25 is valid.
2.you can input an integer as usual.
For example: -1 125 is valid.
3.you can input a rational number in "int/int" format.
For example: 1/3 -1/5 1/-6 is valid.
Notice:
1.if the denominator is 0, it's not valid. the program will set the rational number to 0.
2.if the integer number that need to transfer to rational number is too long, it may fails to transfer,
the rational number will be set to 0.
3.if the fractional number that need to transfer to rational number is too long, it may fails to transfer,
the rational number will be set to 0.
4.if the input is not valid, the rational number will be set to 0;
#include "RationalNum.h"
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
#include <limits.h>
using namespace std;
int absInt(int x) {
if (x >= 0) {
return x;
}
else {
return -x;
}
}
void getFactors (int num, vector<int>& factorSet) {
if (num != 1) {
factorSet.push_back(num);
}
for (int i = 2; i <= sqrt( static_cast<double>(num) ); i++) {
if (num%i == 0) {
factorSet.push_back(i);
factorSet.push_back(num/i);
}
}
}
void simplifyFun(int& a, int& b) {
int tempN = a;
int tempD = b;
int small, temp;
vector<int> factorSet;
if (tempN == tempD) {
a = 1;
b = 1;
return ;
}
else if (tempN == -tempD) {
a = -1;
b = 1;
return ;
}
else if (tempN == 0) {
b = 1;
return ;
}
if (absInt(tempN) < absInt(tempD)) {
small = absInt(tempN);
}
else {
small = absInt(tempD);
}
getFactors(small, factorSet);
for (int i = 0; i < factorSet.size(); i++) {
temp = factorSet[i];
while (tempN%temp == 0 && tempD%temp == 0) {
tempN /= temp;
tempD /= temp;
}
}
a = tempN;
b = tempD;
}
//friend functions definitions
RationalNum operator+(const RationalNum& left, const RationalNum& right) {
RationalNum temp;
int tempLD = left.getDenominator();
int tempRD = right.getDenominator();
simplifyFun(tempLD, tempRD);
temp.setDenominator(left.getDenominator()*tempRD);
temp.setNumerator(left.getNumerator()*tempRD+right.getNumerator()*tempLD);
temp.simplify();
return temp;
}
RationalNum operator-(const RationalNum& left, const RationalNum& right) {
return left+(-right);
}
RationalNum operator*(const RationalNum& left, const RationalNum& right) {
RationalNum temp;
RationalNum temp_2(right.getNumerator(),left.getDenominator());
RationalNum temp_3(left.getNumerator(),right.getDenominator());
int a = temp_2.getDenominator();
int b = temp_2.getNumerator();
int c = temp_3.getDenominator();
int d = temp_3.getNumerator();
temp.setNumerator(b*d);
temp.setDenominator(a*c);
return temp;
}
RationalNum operator/(const RationalNum& left, const RationalNum& right) {
RationalNum temp_1(left.getNumerator(),left.getDenominator());
RationalNum temp_2(right.getDenominator(),right.getNumerator());
return temp_1*temp_2;
}
bool operator==(const RationalNum& left, const RationalNum& right) {
return (left.numerator == right.numerator && left.denominator == right.denominator);
}
bool operator!=(const RationalNum& left, const RationalNum& right) {
return !(left == right);
}
bool operator<(const RationalNum& left, const RationalNum& right) {
int lside = left.getNumerator()*right.getDenominator();
int rside = left.getDenominator()*right.getNumerator();
return (lside < rside);
}
bool operator>(const RationalNum& left, const RationalNum& right) {
int lside = left.getNumerator()*right.getDenominator();
int rside = left.getDenominator()*right.getNumerator();
return (lside > rside);
}
bool operator<=(const RationalNum& left, const RationalNum& right) {
return ( (left < right) || (left == right) );
}
bool operator>=(const RationalNum& left, const RationalNum& right) {
return ( (left > right) || (left == right) );
}
ostream& operator<<(ostream& out, const RationalNum& obj) {
out << obj.numerator;
if (obj.numerator != 0 && obj.denominator != 1) {
out << "/" << obj.denominator;
}
return out;
}
istream& operator>>(istream& in, RationalNum& obj) {
string inputstr;
int num = 0;
int sign = 1;
bool slashExist = false;
bool dotExist = false;
bool validInput = true;
int virtualDenominator = 1;
cin >> inputstr;
for (int i = 0; i < inputstr.size(); i++) {
char temp = inputstr[i];
if (temp == '.') {
if (dotExist == false && slashExist == false && i != 0) {
dotExist = true;
}
else {
validInput = false;
break;
}
}
else if (temp == '/') {
if (dotExist == false && slashExist == false && i != 0) {
slashExist = true;
obj.setNumerator(sign*num);
num = 0;
sign = 1;
}
else {
validInput = false;
break;
}
}
else if (temp == '-') {
if (i == 0){
sign = -sign;
}
else if (inputstr[i-1] == '/') {
sign = -sign;
}
else {
validInput = false;
break;
}
}
else if (temp <= '9' && temp >= '0') {
if (dotExist) {
if (virtualDenominator > INT_MAX/10) {
cout << "this frational is too long to handle.";
validInput = false;
break;
}
else {
virtualDenominator *= 10;
}
}
if (num > INT_MAX/10) {
cout << "this number is too long to handle.";
validInput = false;
break;
}
num *= 10;
num += inputstr[i]-'0';
}
else {
validInput = false;
break;
}
}
if (validInput == false) {
obj.setNumerator(0);
obj.setDenominator(1);
cout << "Input is not valid! The whole set to 0" << endl;
}
else {
if (slashExist == true) {
obj.setDenominator(sign*num);
}
else if (dotExist) {
obj.setNumerator(sign*num);
obj.setDenominator(virtualDenominator);
}
else {
obj.setNumerator(sign*num);
obj.setDenominator(1);
}
}
obj.simplify();
return in;
}
//member function definition
RationalNum::RationalNum() {
setNumerator(0);
setDenominator(1);
}
RationalNum::RationalNum(double x) {
int i = 1;
while (x*i-static_cast<int>(x*i) != 0) {
if (i > INT_MAX/10) {
cout << "this frational number : " << x << " can not be transfer to rational number, it's too long, now set it 0." << endl;
setNumerator(0);
setDenominator(1);
return ;
}
else {
i *= 10;
}
}
setNumerator(x*i);
setDenominator(i);
simplify();
}
RationalNum::RationalNum(int numerator_, int denominator_) {
setNumerator(numerator_);
setDenominator(denominator_);
simplify();
}
RationalNum& RationalNum::operator=(const RationalNum& obj) {
setNumerator(obj.getNumerator());
setDenominator(obj.getDenominator());
return *this;
}
RationalNum& RationalNum::operator+=(const RationalNum& obj) {
*this = *this+obj;
return *this;
}
RationalNum& RationalNum::operator-=(const RationalNum& obj) {
*this = *this-obj;
return *this;
}
RationalNum& RationalNum::operator*=(const RationalNum& obj) {
*this = *this*obj;
return *this;
}
RationalNum& RationalNum::operator/=(const RationalNum& obj) {
*this = *this/obj;
return *this;
}
RationalNum& RationalNum::operator++() {
*this = *this+1;
return *this;
}
RationalNum RationalNum::operator++(int) {
RationalNum before = *this;
*this = *this+1;
return before;
}
RationalNum& RationalNum::operator--() {
*this = *this-1;
return *this;
}
RationalNum RationalNum::operator--(int) {
RationalNum before = *this;
*this = *this-1;
return before;
}
RationalNum RationalNum::operator+() const {
return *this;
}
RationalNum RationalNum::operator-() const {
RationalNum temp;
temp.setNumerator(-getNumerator());
temp.setDenominator(getDenominator());
return temp;
}
void RationalNum::setNumerator(int numerator_) {
numerator = numerator_;
}
int RationalNum::getNumerator() const {
return numerator;
}
void RationalNum::setDenominator(int denominator_) {
if (denominator_ == 0) {
denominator = 1;
numerator = 0;
cout << "Denominator is 0! Not good! THe whole is set to 0." << endl;
}
else {
denominator = denominator_;
}
}
int RationalNum::getDenominator() const {
return denominator;
}
void RationalNum::simplify() {
int tempN = numerator;
int tempD = denominator;
simplifyFun(tempN,tempD);
setNumerator(tempN);
setDenominator(tempD);
}
#ifndef RATIONAL_NUM
#define RATIONAL_NUM
#include <iostream>
using namespace std;
class RationalNum {
friend RationalNum operator+(const RationalNum& left, const RationalNum& right);
friend RationalNum operator-(const RationalNum& left, const RationalNum& right);
friend RationalNum operator*(const RationalNum& left, const RationalNum& right);
friend RationalNum operator/(const RationalNum& left, const RationalNum& right);
friend bool operator==(const RationalNum& left, const RationalNum& right);
friend bool operator!=(const RationalNum& left, const RationalNum& right);
friend bool operator<(const RationalNum& left, const RationalNum& right);
friend bool operator>(const RationalNum& left, const RationalNum& right);
friend bool operator<=(const RationalNum& left, const RationalNum& right);
friend bool operator>=(const RationalNum& left, const RationalNum& right);
friend ostream& operator<<(ostream& out, const RationalNum& obj);
friend istream& operator>>(istream& in, RationalNum& obj);
public:
RationalNum();
RationalNum(double x);
RationalNum(int numerator_, int denominator_ = 1);
RationalNum& operator=(const RationalNum& obj);
RationalNum& operator+=(const RationalNum& obj);
RationalNum& operator-=(const RationalNum& obj);
RationalNum& operator*=(const RationalNum& obj);
RationalNum& operator/=(const RationalNum& obj);
RationalNum& operator++();
RationalNum operator++(int);
RationalNum& operator--();
RationalNum operator--(int);
RationalNum operator+() const;
RationalNum operator-() const;
void setNumerator(int numerator_);
int getNumerator() const;
void setDenominator(int denominator_);
int getDenominator() const;
private:
int numerator;
int denominator;
void simplify();
};
#endif
@ph3rin
Copy link

ph3rin commented Dec 17, 2019

using namespace std;

in a header file should be avoided.

@swigger
Copy link

swigger commented Jan 27, 2024

getFactors is terrible slow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment