# Thread: Fraction Class

1. ## Fraction Class

Assignment:
Design a fraction class.

A fraction is a number made up of a numerator and a denominator. Design a class to implement this.

Obviously we’d like to be able to use the normal operators for mathematical operations (+,-,*, /), comparison operations(==, !=, and <), incrementation, decrementation, input and output.

We don’t need to worry about reducing the fraction. In other words, 4/2 is fine, there’s no need to runt hat into 2/1.

Incrementation and decrementation should add or subtract (as appropriate) 1/1 to the object. Input is in the form of “num denom”. Output is in the form “num/denom”

Code:
```#include <iostream>
#include <string>
using namespace std;

class fraction {
private:
int numerator;
int denominator;

public:
int getNum() {return numerator;}
int getDenom() {return denominator;}
fraction();
fraction(int,int);
//fraction(int num = 1, int denom = 1):numerator(num), denominator(denom) {}
fraction operator+(fraction);
fraction operator-(fraction);
fraction operator*(fraction);
fraction operator/(fraction);
fraction& operator++();
fraction& operator--();
bool operator==(fraction);
bool operator!=(fraction);
bool operator<(fraction);
friend ostream& operator<<(ostream &out, const fraction& value);
friend istream& operator>>(istream &in, fraction& value);
string print();
};

fraction::fraction(int num, int denom){
numerator = num;
denominator = denom;
}

fraction fraction::operator+(fraction Frac){
if(numerator == 0 || Frac.getNum() == 0){
if (numerator != 0){
return fraction(numerator,denominator);
}
else{
return fraction(Frac.getNum(),Frac.getDenom());
}
}
else{
return fraction((numerator*Frac.getDenom()) + (denominator*Frac.getNum()), denominator*Frac.getDenom());
}

}

fraction fraction::operator-(fraction Frac){
if(numerator == 0 || Frac.getNum() == 0){
if (numerator != 0){
return fraction(numerator,denominator);
}
else{
return fraction(Frac.getNum(),Frac.getDenom());
}
}
else{
return fraction((numerator*Frac.getDenom()) - (denominator*Frac.getNum()), denominator*Frac.getDenom());
}

}

fraction fraction::operator*(fraction Frac){
return fraction((Frac.getNum()*numerator), (Frac.getDenom()*denominator));
}

fraction fraction::operator/(fraction Frac){
return fraction((Frac.getNum()*denominator), (Frac.getDenom()*numerator));
}

bool fraction::operator==(fraction Frac){
return((Frac.getNum() == numerator) && (Frac.getDenom() == denominator));
}

bool fraction::operator!=(fraction Frac){
return((Frac.getNum() != numerator) || (Frac.getDenom() != denominator));
}

bool fraction::operator<(fraction Frac){
double first, second;
if(denominator != 0){
first = numerator/ (double) denominator;
}
else{
first = 0.0;
}
if(Frac.getDenom() != 0){
second = Frac.getNum()/ (double) Frac.getDenom();
}
else{
second = 0.0;
}
return(first < second);
}

fraction& fraction::operator++(){
if(denominator != 0){
numerator += denominator;
return *this;
}
else{
cout<< "Enter a proper fraction!";
}

}

fraction& fraction::operator--(){
if(denominator != 0){
numerator -= denominator;
return *this;
}
else{
cout<< "Enter a proper fraction!";
}

}

ostream &operator<<(ostream& out, const fraction& value){
out<< value.numerator<<"/"<<value.denominator;
return out;
}

istream& operator>>(istream &in, fraction& value){
int num, denom;
in>>num>>denom;
value = fraction(num, denom);
return in;
}

int main(){
int Num2, Denom2;
fraction f1,f2;

cout<< "Enter the first numerator: ";
cin>> Num2;
cout<< "Enter the first denominator: ";
cin>> Denom2;
f1(Num2,Denom2);
cout<<"The first fraction is: "<<f1.print()<<endl;

cout<< "Enter the second numerator: ";
cin>> Num2;
cout<< "Enter the second denominator: ";
cin>> Denom2;
f2(Num2,Denom2);
cout<<"The second fraction is: "<<f1.print()<<endl;

cout<<"The following operations were performed:"<<endl;

fraction f3 = f1 + f2;
cout<<"Addition: "<<f1.print() << " + " << f2.print() << " = " << f3.print()<<endl;

f3 = f1 - f2;
cout<<"Subtraction: "<<f1.print() << " - " << f2.print() << " = " << f3.print()<<endl;

f3 = f1 * f2;
cout<<"Multiplication: "<<f1.print() << " * " << f2.print() << " = " << f3.print()<<endl;

f3 = f1 / f2;
cout<<"Division: "<<f1.print() << " ÷ " << f2.print() << " = " << f3.print()<<endl;

++f1;
cout<<"Incrementation: "<<f1.print() << " ++ " << " = " << f1.print()<<endl;

--f2;
cout<<"Decrementation: "<<f2.print() << " -- " << " = " << f2.print()<<endl;

}```
I keep getting an error: error C2064: term does not evaluate to a function taking 2 arguments.
This is in reference to line 158 and 166
Any ideas on what I'm doing wrong? Does the code make sense in general?

2. Looking at:
Code:
`f1(Num2,Denom2);`
My guess is that you want to create f1 by calling its constructor with the two arguments. If so, you should write:
Code:
`fraction f1(Num2,Denom2);`
In fact, variables should be declared near first use, so doing this is good practice. The same goes for f2.

3. That got rid of those two errors but gave me two new ones, and two warnings:

Warning 1 warning C4715: 'fraction:: operator++' : not all control paths return a value
Warning 2 warning C4715: 'fraction:: operator--' : not all control paths return a value
Error 3 error LNK2019: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall fraction:rint(void)" (?print@fraction@@QAE?AV?\$basic_string@DU?\$char_tr aits@D@std@@V?\$allocator@D@2@@std@@XZ) referenced in function _main
And...

Error 4 error LNK1120: 1 unresolved externals

4. The warnings about "not all control paths return a value" just means that there is a condition in which the function has no return statement that will be executed, yet it is declared as returning a value. In this case, an appropriate solution is to throw an exception instead of just printing an error message.

As for the error: you did not implement the print member function yet you called it several times. In fact, since you overloaded operator<< you don't need the print member function to begin with.

5. Okay, it works. Thank you!!

6. You may have fixed the compiler errors, but you have several other issues, including but not limited to:

Not implementing both pre and post increment / decrement.
Lack of const-correctness.
having cout statements inside the increment/decrement. (Consider exceptions instead)
With the absense of reducing the fraction, you should be doing some extra work to ensure that the fractions 4/2 and 2/1 compare equal, for example.
The far better way to implement operator less-than is to rearrange the use of division into a multiplication.
Operator >> does not mirror operator << (it does not skip the slash).

7. Originally Posted by iMalc
You may have fixed the compiler errors, but you have several other issues, including but not limited to:

Not implementing both pre and post increment / decrement.
Lack of const-correctness.
having cout statements inside the increment/decrement. (Consider exceptions instead)
With the absense of reducing the fraction, you should be doing some extra work to ensure that the fractions 4/2 and 2/1 compare equal, for example.
The far better way to implement operator less-than is to rearrange the use of division into a multiplication.
Operator >> does not mirror operator << (it does not skip the slash).
I only wrote the pre increment/decrement operators because the assignment did not explicitly state to implement post. I dont quite understand what you're talking about in reference to the "<" operator. Thank you for the advice!

8. (a/b < c/d)
will be the same as

(a*d < c*b)

but the second expression is quicker

9. Originally Posted by vart
(a/b < c/d)
will be the same as

(a*d < c*b)

but the second expression is quicker
Yes, and it avoids the need to test for zero demoninators first since it cant divide by zero. Pretty much turns it into a one-liner.

10. Originally Posted by iMalc
Yes, and it avoids the need to test for zero denominators first since it cant divide by zero. Pretty much turns it into a one-liner.
Oh one word of warning with this, you may need to enforce the strict policy that the denominator can never be negative, though oviously the numerator can. So 1 / -2 must always be stored as -1 / 2.

Further hint: The same multiplication instead of division change also solves your equality and inequality issues.

11. having cout statements inside the increment/decrement. (Consider exceptions instead)
O_o

If he wishes his class to consider a denominator of zero to be an error, entirely reasonable, he shouldn't allow an instance of the fraction class to exist which has a zero denominator in the first place.

This check should be in the constructor/stream operators signalling, preferably, with an exception and setting `ios' flags.

Soma

12. Once all of this is basically working, you may consider reducing the fraction produced by an operator by the greatest common divisor. The Euclid method would probably easiest to implement. Wiki article:

Euclidean algorithm - Wikipedia, the free encyclopedia

13. Originally Posted by phantomotap
O_o

If he wishes his class to consider a denominator of zero to be an error, entirely reasonable, he shouldn't allow an instance of the fraction class to exist which has a zero denominator in the first place.

This check should be in the constructor/stream operators signalling, preferably, with an exception and setting `ios' flags.

Soma
Yes that is certainly the better option.

Popular pages Recent additions