Can anyone explain this error any why I am getting it? I believe I've got all of the arithmetic down in my separate class.
This program stores and manipulates fractions, while testing overloading.
Thank you in advance.
I am trying to test this in the driver with the output looking like this.
f1 = 3/6, f2 = 4/5
f1 + f2 = 39/30 = 13/10 = 1.3
f1 - f2 = -9/30 = -3/10 = -0.3
f1 * f2 = 12/30 = 2/5 = 0.4
f1 / f2 = 15/24 = 5/8 = 0.625
Enter a fraction [numerator denominator]: 2 5
You entered 2/5
My Fraction.cpp class
#include "Fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction(const int numerator, const int denominator) { }
int Fraction::getNumerator() const {
return numerator;
}
int Fraction::getDenominator() const {
return denominator;
}
int Fraction::gcd() const {
int n = numerator;
int d = denominator;
int temp;
while (d!=0) {
temp = n % d;
n = d;
d = temp;
}
return n;
}
void Fraction::setNumerator(const int numerator) {
this->numerator = numerator;
}
void Fraction::setDenominator(const int denominator) {
this->denominator = denominator;
}
string Fraction::toString() const {
return "";
}
double Fraction::returnDecimal() const {
double a = (double) getNumerator();
double b = (double) getDenominator();
return (a / b);
}
void Fraction::reduce() {
int a = gcd();
int b = numerator / a;
int c = denominator / a;
setNumerator(b);
setDenominator(c);
}
Fraction Fraction::operator +(const Fraction& f) const {
Fraction temp;
int a = getNumerator();
int b = getDenominator();
int c = f.getNumerator();
int d = f.getDenominator();
int tempOne = b;
int tempTwo = d;
a = a * tempTwo;
b = b * tempTwo;
c = c * tempOne;
d = d * tempOne;
temp.setNumerator(a+c);
temp.setDenominator(d);
return temp;
}
Fraction Fraction::operator -(const Fraction& f) const {
Fraction temp;
int a = getNumerator();
int b = getDenominator();
int c = f.getNumerator();
int d = f.getDenominator();
int tempOne = b;
int tempTwo = d;
a = a * tempTwo;
b = b * tempTwo;
c = c * tempOne;
d = d * tempOne;
temp.setNumerator(a-c);
temp.setDenominator(d);
return temp;
}
Fraction Fraction::operator *(const Fraction& f) const {
Fraction temp;
temp.setNumerator(getNumerator() * f.getNumerator());
temp.setDenominator(getDenominator() * f.getDenominator());
return temp;
}
Fraction Fraction::operator /(const Fraction& f) const {
Fraction temp;
temp.setNumerator(getNumerator() * f.getDenominator());
temp.setDenominator(getDenominator() * f.getNumerator());
return temp;
}
bool Fraction::operator ==(const Fraction& f) const {
return ( (getNumerator() == f.getNumerator()) && (getDenominator() == f.getDenominator()) );
}
bool Fraction::operator !=(const Fraction& f) const {
return !( (getNumerator() == f.getNumerator()) && (getDenominator() == f.getDenominator()) );
}
bool Fraction::operator <(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) < (c/d));
}
bool Fraction::operator <=(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) <= (c/d));
}
bool Fraction::operator >(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) > (c/d));
}
bool Fraction::operator >=(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) >= (c/d));
}
ostream& operator <<(ostream& out, const Fraction& f) {
out << f.getNumerator() << "/" << f.getDenominator();
return out;
}
istream& operator >>(istream& in, Fraction& f) {
int a;
int b;
in >> a >> b;
f.setNumerator(a);
f.setDenominator(b);
return in;
}
My main class.
#include <iostream>
#include "Fraction.h"
#include "Fraction.cpp"
using namespace std;
int main(int argc, const char * argv[])
{
Fraction::getNumerator() const;
Fraction::getDenominator() const;
Fraction::gcd() const;
Fraction::setNumerator(<#const int numerator#>);
Fraction::setDenominator(<#const int denominator#>);
Fraction::toString();
Fraction::returnDecimal() const;
Fraction::reduce();
return 0;
}
Fraction.h
#include <iostream>
#include <string>
using namespace std;
class Fraction {
private:
int numerator;
int denominator;
int gcd() const;
public:
Fraction(const int numerator = 0, const int denominator = 0);
int getNumerator() const;
int getDenominator() const;
void setNumerator(const int numerator);
void setDenominator(const int denominator);
string toString() const;
double returnDecimal() const;
void reduce();
bool operator ==(const Fraction& f) const;
bool operator !=(const Fraction& f) const;
bool operator <(const Fraction& f) const;
bool operator <=(const Fraction& f) const;
bool operator >(const Fraction& f) const;
bool operator >=(const Fraction& f) const;
Fraction operator +(const Fraction& f) const;
Fraction operator -(const Fraction& f) const;
Fraction operator *(const Fraction& f) const;
Fraction operator /(const Fraction& f) const;
friend ostream& operator <<(ostream&, const Fraction&);
friend istream& operator >>(istream&, Fraction&);
};
Fraction is a class. You need an object of that class in order to call its (nonstatic) functions.
Fraction f;
f.getNumerator();
I know there are plenty of questions like these, but I couldn't find a solution that worked for me.
Okay, I am trying to make simple fraction calculator than can add or subtract any number of functions and write the answer as a reduced fraction.
Example: input=
3/2 + 4/
8
, output =
2
I am trying overload operators in order to accomplish this.
So in the program, I am trying to develop the input consists of an expression made of fractions separated by the operators '+'or '-'.
The number of fractions in the expression is arbitrary.
Each of the following 6 lines is an example of valid input expression:
1/2 + 3/4
1/2 -5/7+3/5
355/113
3 /9-21/ -7
4/7-5/-8
-2/-3+7/5
The problem that I am having is that in when I run my Main CPP program it has a class redefinition error:
fraction.cpp:6:7: error: redefinition of 'Fraction'
class Fraction
^
./Fraction.h:7:7: note: previous definition is here
class Fraction{
However, that should not be a problem because I declared the class and member functions in my header files and defined them in my CPP file.
My following code is below:
Header File
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
using namespace std;
class Fraction{
public:
Fraction(int , int );
int fraction(int,int);
void reduce_fraction(int *, int *);
Fraction& operator+(const Fraction& n);
Fraction& operator-(const Fraction& n);
friend ostream& operator<<(ostream &os, const Fraction& n);
friend istream& operator>>(istream &is, const Fraction& n);
};
#endif
CPP File
#include <iostream>
using namespace std;
#include "Fraction.h"
#include <stdexcept>
class Fraction
{
public:
Fraction::Fraction(int a, int b);
int find_gcd(int n1, int n2);
void reduce_fraction(int *nump, int *denomp)
{
int gcd;
gcd = find_gcd(*nump, *denomp);
*nump = *nump / gcd;
*denomp = *denomp / gcd;
if ((*denomp<0 && *nump < 0 ))
{
*denomp*=-1;
*nump*=-1;
}
else if (*denomp < 0 && *nump >0){
*denomp*=-1;
}
if ( *denomp ==0) {
throw invalid_argument( "Error: zero denominator" );
}
}
Fraction& Fraction::operator+(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) + (n.denom * n.nump);
return Fraction(numera,denom);
}
Fraction& Fraction::operator-(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) - (n.denom* n.nump);
return Fraction(numera, denom);
}
friend ostream& operator<<(ostream &os, Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
friend istream& operator>>(istream &os, Fraction& n)
{
char slash = 0;
return is >> n.numera >> slash >> n.denom;
}
};
#include <iostream>
using namespace std;
#include "Fraction.h"
#include <stdexcept>
class Fraction
{
public:
Fraction::Fraction(int a, int b);
int find_gcd(int n1, int n2);
void reduce_fraction(int *nump, int *denomp)
{
int gcd;
gcd = find_gcd(*nump, *denomp);
*nump = *nump / gcd;
*denomp = *denomp / gcd;
if ((*denomp<0 && *nump < 0 ))
{
*denomp*=-1;
*nump*=-1;
}
else if (*denomp < 0 && *nump >0){
*denomp*=-1;
}
if ( *denomp ==0) {
throw invalid_argument( "Error: zero denominator" );
}
}
Fraction& Fraction::operator+(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) + (n.denom * n.nump);
return Fraction(numera,denom);
}
Fraction& Fraction::operator-(const Fraction& n) {
int denom = *denomp * n.denom;
int numera = (*nump * n.numera) - (n.denom* n.nump);
return Fraction(numera, denom);
}
friend ostream& operator<<(ostream &os, Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
friend istream& operator>>(istream &os, Fraction& n)
{
char slash = 0;
return is >> n.numera >> slash >> n.denom;
}
};
MAIN CPP FILE
#include "Fraction.h"
#include <iostream>
using namespace std;
int main()
{
Fraction x(2,3);
Fraction y(6,-2);
cout << x << endl;
cout << y << endl;
cin >> y;
cout << y << endl;
Fraction z = x + y;
cout << x << " + " << y << " = " << z << endl;
}
I am essentially having trouble with understanding why I am getting the previous definition error and how exactly to fix it. Also, if you see anything else wrong with my implementation in this program I would appreciate you telling me!
Thank you very much!
The way to define member functions in Fraction.cpp is not like this:
class Fraction
{
public:
void reduce_fraction(int *nump, int *denomp)
{
...
}
}
but rather like this:
void Fraction::reduce_fraction(int *nump, int *denomp)
{
...
}
More generally, you should not write this much code before testing any of it.
I am striving to test every function in this class and I cannot test the function that will assign a numerator and denominator to the constructor that takes no arguments here is my code. I get this error request for a member 'numerator' in 'first' which is of non class type 'Rational'
#include "Rational.h"
#include <iostream>
#include <string>
#include "GCD.h"
#include <assert.h>
using namespace std;
Rational:: Rational()
{
myNumerator = 1;
myDenominator = 1;
}
Rational:: Rational(int numerator, int denominator)
{
assert(denominator != 0);
myNumerator = numerator;
myDenominator = denominator;
reduce();
}
Rational:: Rational(const Rational &r)
{
myNumerator = r.myNumerator;
myDenominator = r.myDenominator;
}
const Rational& Rational :: operator = (const Rational &rhs)
{
if (this != &rhs)
{
myNumerator = rhs.myNumerator;
myDenominator = rhs.myDenominator;
return rhs;
}
}
int Rational:: numerator(int a) const
{
myNumerator = a;
return myNumerator;
}
int Rational:: denominator(int b) const
{
myNumerator = b;
return myDenominator;
}
void Rational:: reduce()
{
int commonDivisor = GCD(myNumerator, myDenominator);
myNumerator = myNumerator / commonDivisor;
myDenominator = myDenominator / commonDivisor;
}
Rational operator + (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator();
int denominator = lhs.denominator() * rhs.denominator();
Rational sum(numerator, denominator);
return sum;
}
Rational operator - (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator();
int denominator = lhs.denominator() * rhs.denominator();
Rational difference(numerator, denominator);
return difference;
}
Rational operator * (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.numerator();
int denominator = lhs.denominator() * rhs.denominator();
Rational product(numerator, denominator);
return product;
}
Rational operator / (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator();
int denominator = lhs.denominator() * rhs.numerator();
Rational product(numerator, denominator);
return product;
}
ostream& operator << (ostream & os, const Rational &r)
{
os << r.numerator() << "/" << r.denominator();
return os;
}
istream& operator >> (istream &is, Rational &r)
{
char divisionSymbol;
int numerator = 0, denominator = 0;
is >> numerator >> divisionSymbol >> denominator;
assert(divisionSymbol == '/');
assert(denominator != 0);
Rational number(numerator, denominator);
r = number;
return is;
}
#include <iostream>
#include "Rational.h"
using namespace std;
int main()
{
Rational first(), second(75, 350), third(13, 55);
Rational fourth(second);
cout << first << endl << second << endl << third << endl << fourth <<endl;
first.numerator(3)const;
first.denominator(5)const;
cout << first;
}
Rational first(); is parsed as a function declaration. it is known as Most vexing parse.
You may use Rational first;
And in C++11, you may also use Rational first{};
There is no reason to mark your functions as const if you're going to modify your member variables. It's a promise that you won't modify *this and you do so anyway. So simply remove it. You also provide const "getters" anyway.
int numerator(int a);
int numerator() const {return myNumerator;}
int denominator(int b);
int denominator() const {return myDenominator;}
int Rational:: numerator(int a)
{
// ..
}
int Rational:: denominator(int b)
{
// ..
}
Your copy assignment operator also doesn't make sense. I suggest changing it:
if (this == &rhs)
{
return *this;
}
myNumerator = rhs.numerator();
myDenominator = rhs.denominator();
return *this;
Now for the error others pointed out, your compiler happily warns that empty parentheses interpreted as a function declaration. Simply remove the parentheses or replace them with brackets {} in C++11 mode. Also, you don't need the const keyword when calling a const member function.
Rational first, second(75, 350), third(13, 55);
first.numerator(3);
first.denominator(5);
I have a class called Fraction :
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
using namespace std;
class Fraction
{
// data
int m_iNom;
int m_iDenom;
// operations
int gcd (int i, int j);
void reduce ();
public:
Fraction (int nn=0, int dn=1); // 1 declaration = 3 constructors
Fraction (const Fraction& fr); //C.Ctor
~Fraction (); //Dtor
Fraction& operator = (const Fraction &fr); //assignment
Fraction& operator ++ (); // prefix - ++a
const Fraction operator ++ (int); // postfix - a++
friend const Fraction operator + (const Fraction &f1, const Fraction &f2);
friend const Fraction operator - (const Fraction &f1, const Fraction &f2);
friend const Fraction operator * (const Fraction &f1, const Fraction &f2);
friend const Fraction operator / (const Fraction &f1, const Fraction &f2);
Fraction& operator += (const Fraction &f);
operator double () { return double (m_iNom) / m_iDenom; } //casting operator
friend istream& operator >> (istream &is, Fraction &f);
friend ostream& operator << (ostream &os, const Fraction &f);
const int& operator[] (int i) const;
int& operator [] (int i);
};
#endif
with the next implementation file :
#include "Fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction (int nn, int dd) :
m_iNom (nn), m_iDenom (dd) {
if (m_iDenom == 0)
m_iDenom = 1;
reduce ();
cout<<"Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
Fraction::Fraction (const Fraction & fr){
m_iNom=fr.m_iNom;
m_iDenom=fr.m_iDenom;
cout<<"C.Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
Fraction::~Fraction() {
cout<<"del: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
int Fraction::gcd (int i, int j) {
if ((i == 0) || (j == 0))
return i + j;
while (i %= j) {
int t = i;
i = j;
j = t;
}
return j;
}
void Fraction::reduce () {
int g = gcd (m_iNom, m_iDenom);
m_iNom /= g;
m_iDenom /= g;
}
const Fraction operator + (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom + f1.m_iDenom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator - (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom - f1.m_iDenom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator * (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator / (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom;
int dd = f1.m_iDenom * f2.m_iNom;
return Fraction (nn, dd);
}
Fraction& Fraction::operator = (const Fraction &f)
{
m_iNom = f.m_iNom;
m_iDenom = f.m_iDenom;
cout<<"OP = - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
return *this;
}
Fraction& Fraction::operator += (const Fraction &f) {
(*this) = (*this) + f;
return *this;
}
Fraction& Fraction::operator ++ ()
{
m_iNom += m_iDenom;
reduce ();
return *this;
}
const Fraction Fraction::operator ++ (int)
{
int nn = m_iNom;
int dd = m_iDenom;
m_iNom += m_iDenom;
reduce ();
return Fraction (nn, dd);
}
istream& operator >> (istream &is, Fraction &frac)
{
char divSign;
is >> frac.m_iNom >> divSign >> frac.m_iDenom;
if (frac.m_iDenom == 0)
frac.m_iDenom = 1;
frac.reduce ();
return is;
}
ostream& operator << (ostream& os, const Fraction &frac)
{
return os << frac.m_iNom << "/" << frac.m_iDenom;
}
int& Fraction::operator [] (int i){
cout<<"reg []"<<endl;
if (i==1)
return m_iNom;
return m_iDenom;
}
const int& Fraction::operator[] (int i) const{
cout<<"const []"<<endl;
if (i==1)
return m_iNom;
return m_iDenom;
}
and I'm trying to do the action Fraction f4=f2+2; but I get the following compiler error:
..\main.cpp:13: error: ambiguous overload for 'operator+' in 'f2 + 2'
..\main.cpp:13: note: candidates are: operator+(double, int) <built-in>
..\Fraction.h:27: note: const Fraction operator+(const Fraction&, const Fraction&)
But how could that be , if I have a conversion Constructor (please notice the Ctor in the .h file with the default values) with one argument which is suppose to convert the "2" into a Fraction ...then what's might the be the problem ?
thanks
Ronen
Edit :
here's the main file (if it would help)
#include <iostream>
using namespace std;
#include "Fraction.h"
int main() {
Fraction f1(1,2);
Fraction f2(2);
Fraction f3;
Fraction f4=f2+2; // problem's here
f2+f2;
Fraction f5=f2-f1+f4;
return 0;
}
The compiler can't decide whether to convert f2 to double then add double and int, or to construct Fraction from 2 then add two fractions.
Options:
Make operator double() explicit (C++11)
Overload operator + to take ints
Problem is:
operator double ()
defined inside your Fraction class.
While evaluating,
Fraction f4=f2+2;
Compiler has 2 choices:
First Choice:
The compiler can convert f2 to a double using your provided operator function and then it can be used to call the inbuilt operator function:
operator+(double, int);
Second Choice:
The compiler can convert 2 to a object of Fraction using constructor and then call:
const Fraction operator+(const Fraction&, const Fraction&)
The two choices cause an ambiguity and then the compiler complains and reports it to you.
Solution:
Change the name of the double operator function.
The compiler can indeed make 2 choices when you write something like f2+2.
It can first convert 2 to a fraction by using the fraction's constructor and then use the Fraction's + operator.
It can first convert f2 to a double using the Fraction's double operator, and then simply add the double and the integer
You will have to make either the constructor explicit, or give the double-operator an explicit name (e.g. toDouble) to solve the problem.
I have to create a class called Fractions with 2 private fields Numerator, Denominator. And a public constructor that sets Numerator and Denominator to 1 by default. I have included 4 members functions in my my Fractions class: Sum, Difference, Product, Division.
Then I am not sure what to do next. Why does book show fraction equivalences? What do I have to do with that? I guess a very important question would be what parameters should my member functions take?
Also what would be a good way to prohibit denominator of 0? Throw exception or force it to be equal to 1?
Here is the complete source code for the question #5 and #6 (not shown) after struggling with the problem for days. Questions #6 just asks to implement the greatest common divisor function to return fraction in a simplified form. So here it is...
If you think there is a way to optimize this code I'd be happy to hear your responses!
#include <iostream>
using namespace std;
class Fraction
{
private:
int numerator, denominator;
public:
Fraction()
{
numerator = 1;
denominator = 1;
}
Fraction(int n, int d)
{
numerator = n;
if (d==0)
{
cout << "ERROR: ATTEMPTING TO DIVIDE BY ZERO" << endl;
exit(0); // will terminate the program if division by 0 is attempted
}
else
denominator = d;
}
/*In the following functions I am dividing both numerator and denominator by the gcd function.
GCD function accepts both numerator and denominator values. If we had 2 fractions, 1/2 and 1/4
and we passed it into the Sum, the result would be n=6 and d=8. These are the values that GCD
function will accept, find greatest common divisor and return the integer value of 2. In my case
am diving both numerator and denominator on the same line by the greatest common divisor. Although
it probably would be more efficient to create a local int variable and store GCD value in it, but
for such small program it shouldn't make any difference.*/
Fraction Sum(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator+otherFraction.numerator*denominator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Difference(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator-otherFraction.numerator*denominator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Product(Fraction otherFraction)
{
int n = numerator*otherFraction.numerator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Division(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator;
int d = denominator*otherFraction.numerator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
// I got the GCD algorithm from the following source:
// Source C#: http://www.ww.functionx.com/csharp2/examples/gcd.htm
int gcd(int n, int d)
{
int remainder;
while (d != 0)
{
remainder = n % d;
n = d;
d = remainder;
}
return n;
}
void show() // Display method
{
if (denominator == 1) // e.g. fraction 2/1 will display simply as 2
cout << numerator << endl;
else
cout << numerator << "/" << denominator << endl;
}
};
int main()
{
Fraction a(1,2);
Fraction b(1,4);
Fraction c;
c = a.Sum(b); // Result: 3/4
c.show();
c = a.Difference(b); // Result: 1/4
c.show();
c = a.Product(b); // Result: 1/8
c.show();
c = a.Division(b); // Result: 2
c.show();
return 0;
}
You may want to start with just the first part, create the class with two constructors, one if they give the two numbers, and one that defaults to 1.
Then, write the four functions, the assignment is nice enough to give you the equations.
If a denominator is ever equal to zero then I would throw an exception, as that is something the user may be able to fix. If you can show what led to it being zero, for example, if they divide (1/2)/(0/4) then your denominator is zero, which should be an error condition.
One issue you will want to look at is if this will be immutable, so, if I have (1/2) and (2/3) and I do an operation, it should return a new number, not modify either of the two that I passed in. In that case your check is always in the constructor for a zero, but you should explain which operation led to this error.
Also what would be a good way to prohibit denominator of 0? Throw exception or force it to be equal to 1?
That's completely a style question, with no provably correct answer...
But... I'd go with an exception. Again, this is just style. Changing the value silently would be carrying on silently forward having done something other than what the caller asked for.
Another alternative would be to allow 0 denominator, but have a way to inform the user that the current overall value, a/b, is NaN or infinity, or whatever "special value" you care to define.
In any case, document it carefully, so a user of the class can make informed choices.
Your fraction constructor should take a numerator and a denominator as parameters (or a whole number). The entire problem could be solved easily with operator overloading.
And yes, the best way to handle failed constructors is via exceptions. Don't forget to throw the same division_by_zero exception when you're dividing two fractions and the numerator of the denominator is zero.
Your methods could be (assuming your class is named "Fraction"):
Fraction Fraction::sum(Fraction &otherFraction)
Fraction Fraction::difference(Fraction &otherFraction)
Fraction Fraction::product(Fraction &otherFraction)
Fraction Fraction::division(Fraction &otherFraction)
(Using the method names you described - I might go for something different)
Each of these would return a new Fraction object containing the result.
You'd be into bonus points for using operator overloading and re-defining what + - / * meant.
So many questions in one question! Let me answer one (pair) for you:
Why does book show fraction
equivalences? What do I have to do
with that?
Consider this usage of your Fraction class:
TEST(FractionsAreEquivalent)
{
const Fraction one_over_two(1, 2); // 0.5
const Fraction two_over_four(2, 4); // 0.5
const bool equivalent = (one_over_two == two_over_four);
CHECK(equivalent);
}
This uses bool Fraction::operator ==(const Fraction& rhs) const.
Im a new guy so im sorry if my code looks so noob :P
#include<iostream>
using namespace std;
class Fraction
{
private :
int x;//NUMERATOR
int y;//DENOMINATOR
public :
Fraction(int tx = 0, int ty = 1)
{
if(ty == 0)
{
x = 0;
y = 1;
exit(0);
}else
{
x = tx;
y = ty;
}
}
void simplify()
{
for(int i = x; i >1;i--)
{
if(x%i == 0 && y%i == 0)
{
x = x/i;
y = y/i;
}
}
}
void Input()
{
cout<<"Input NUMERATOR: ";
cin>>x;
cout<<"Input DENOMINATOR: ";
cin>>y;
if(y==0)
{
cout<<"ERROR";
exit(0);
}
}
void Display()
{
cout<< x << "/" << y <<endl;
}
Fraction operator + (Fraction f){
Fraction temp;
temp.x = x * f.y + y * f.x;
temp.y = y * f.y;
return temp;
}
Fraction operator - (Fraction f){
Fraction temp;
temp.x = x * f.y - y * f.x;
temp.y = y * f.y;
return temp;
}
Fraction operator * (Fraction f){
Fraction temp;
temp.x = x * f.x ;
temp.y = y * f.y;
return temp;
}
Fraction operator / (Fraction f){
Fraction temp;
temp.x = x * f.y ;
temp.y = y * f.x;
return temp;
}
};
int main ()
{
Fraction f1;
f1.Input();
cout<<"Fraction: ";
f1.simplify();
f1.Display();
Fraction f2;
f2.Input();
cout<<"Fraction: ";
f2.simplify();
f2.Display();
Fraction f3,f4,f5,f6;
f3 = f1 + f2;
f4 = f1 - f2;
f5 = f1 * f2;
f6 = f1 / f2;
cout<<"Sum"<<endl;
f3.simplify();
f3.Display();
cout<<"Difference"<<endl;
f4.simplify();
f4.Display();
cout<<"Product"<<endl;
f5.simplify();
f5.Display();
cout<<"Division"<<endl;
f6.simplify();
f6.Display();
return 0;
}
Blockquote
I created a version of this Fractions class, and although my coding is terrible, it should work. Note that I defined the <=> operator, which is introduced in C++20, and defines <, >, <=, >= automatically. If you don't have that, you could use std::rel_ops or just defining them all one by one.
Fraction.h:
#include <memory>
#include <numeric>
#include <string>
class Fraction
{
private:
long long num{ 1 };
long long denom{ 1 };
inline void simplify() {
auto gcd{ std::make_unique<long long>(std::gcd(num, denom)) };
num /= *gcd;
denom /= *gcd;
gcd.reset();
if (denom < 0) {
num = -num;
denom = -denom;
}
}
public:
Fraction(double numerator = 1, double denominator = 1);
Fraction(double numerator, double denominator, int integer_part);
Fraction(const Fraction& f);
long long numerator() const;
long long denominator() const;
auto setnumerator(long long nv);
auto setdenominator(long long nv);
double value() const;
Fraction reciprocal() const;
std::string str(size_t mode = 0) const;
bool operator==(const Fraction& f) const;
auto operator<=>(const Fraction& f) const;
bool operator==(size_t s) const;
auto operator<=>(size_t s) const;
friend bool operator== (size_t s, Fraction& f);
friend auto operator<=> (size_t s, Fraction& f);
bool operator==(double d) const;
auto operator<=>(double d) const;
friend bool operator== (double d, Fraction& f);
friend auto operator<=> (double d, Fraction& f);
Fraction operator+(const Fraction& f) const;
Fraction operator+(size_t s) const;
Fraction operator+(double d) const;
friend Fraction operator+(size_t s, const Fraction& f);
friend Fraction operator+(double d, const Fraction& f);
Fraction operator-(const Fraction& f) const;
Fraction operator-(size_t s) const;
Fraction operator-(double d) const;
friend Fraction operator-(size_t s, const Fraction& f);
friend Fraction operator-(double d, const Fraction& f);
Fraction operator*(const Fraction& f) const;
Fraction operator*(size_t s) const;
Fraction operator*(double d) const;
friend Fraction operator*(size_t s, const Fraction& f);
friend Fraction operator*(double d, const Fraction& f);
Fraction operator/(const Fraction& f) const;
Fraction operator/(size_t s) const;
Fraction operator/(double d) const;
friend Fraction operator/(size_t s, const Fraction& f);
friend Fraction operator/(double d, const Fraction& f);
Fraction operator%(const Fraction& f) const;
Fraction operator%(size_t s) const;
Fraction operator%(double d) const;
friend size_t operator%(size_t s, const Fraction& f);
friend double operator%(double d, const Fraction& f);
Fraction& operator+=(const Fraction& f);
Fraction& operator+=(size_t s);
Fraction& operator+=(double d);
friend size_t operator+=(size_t s, Fraction& f);
friend double operator+=(double d, Fraction& f);
Fraction& operator-=(const Fraction& f);
Fraction& operator-=(size_t s);
Fraction& operator-=(double d);
friend size_t operator-=(size_t s, Fraction& f);
friend double operator-=(double d, Fraction& f);
Fraction& operator*=(const Fraction& f);
Fraction& operator*=(size_t s);
Fraction& operator*=(double d);
friend size_t operator*=(size_t s, Fraction& f);
friend double operator*=(double d, Fraction& f);
Fraction& operator/=(const Fraction& f);
Fraction& operator/=(size_t s);
Fraction& operator/=(double d);
friend size_t operator/=(size_t s, Fraction& f);
friend double operator/=(double d, Fraction& f);
Fraction& operator%=(const Fraction& f);
Fraction& operator%=(size_t s);
Fraction& operator%=(double d);
friend size_t operator%=(size_t s, Fraction& f);
friend double operator%=(double d, Fraction& f);
Fraction& operator++();
Fraction operator++(int);
Fraction& operator--();
Fraction operator--(int);
Fraction operator+();
Fraction operator-();
long long operator[](int i);
};
Fraction.cpp:
#include "Fraction.h"
#include <limits>
#include <sstream>
Fraction::Fraction(double numerator, double denominator)
{
double tsn{ numerator }, tsd{ denominator };
while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
tsn *= 10;
tsd *= 10;
}
num = tsn;
denom = tsd;
simplify();
}
Fraction::Fraction(double numerator, double denominator, int integer_part)
{
numerator += denominator * integer_part;
double tsn{ numerator }, tsd{ denominator };
while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
tsn *= 10;
tsd *= 10;
}
num = tsn;
denom = tsd;
simplify();
}
Fraction::Fraction(const Fraction& f)
{
num = f.numerator();
denom = f.denominator();
}
long long Fraction::numerator() const
{
return num;
}
long long Fraction::denominator() const
{
return denom;
}
auto Fraction::setnumerator(long long nv)
{
num = nv;
simplify();
return this;
}
auto Fraction::setdenominator(long long nv)
{
denom = nv;
simplify();
return this;
}
double Fraction::value() const
{
return static_cast<double>(num) / denom;
}
Fraction Fraction::reciprocal() const
{
return Fraction(denom, num);
}
std::string Fraction::str(size_t mode) const
{
std::stringstream ss;
if (mode == 0) {
ss << num;
if (denom != 1) {
ss << '/' << denom;
}
}
else {
if (num % denom == 0 || denom == 1) {
ss << num / denom;
}
else {
if (abs(denom) > abs(num)) {
ss << num << '/' << denom;
}
else if (num < 0) {
ss << '-' << '(' << (num / denom) << ' ' << -(num % denom) << '/' << denom << ')';
}
else {
ss << (num / denom) << ' ' << num % denom << '/' << denom;
}
}
}
return ss.str();
}
bool Fraction::operator==(const Fraction& f) const
{
return value() == f.value();
}
auto Fraction::operator<=>(const Fraction& f) const
{
return value() <=> f.value();
}
bool Fraction::operator==(size_t s) const
{
return value() == s;
}
auto Fraction::operator<=>(size_t s) const
{
return value() <=> s;
}
bool operator==(size_t s, const Fraction& f)
{
return s == f.value();
}
auto operator<=>(size_t s, const Fraction& f)
{
return s <=> f.value();
}
bool Fraction::operator==(double d) const
{
return value() == d;
}
auto Fraction::operator<=>(double d) const
{
return value() <=> d;
}
bool operator==(double d, Fraction& f)
{
return f.value() == d;
}
auto operator<=>(double d, Fraction& f)
{
return f.value() <=> d;
}
Fraction Fraction::operator+(const Fraction& f) const
{
return Fraction(num * f.denominator() + f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator+(size_t s) const
{
return Fraction(s * denom + num, denom);
}
Fraction Fraction::operator+(double d) const
{
return *this + Fraction(d);
}
Fraction operator+(size_t s, const Fraction& f)
{
return f + s;
}
Fraction operator+(double d, const Fraction& f)
{
return f + d;
}
Fraction Fraction::operator-(const Fraction& f) const
{
return Fraction(num * f.denominator() - f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator-(size_t s) const
{
return Fraction(num - (s * denom), denom);
}
Fraction Fraction::operator-(double d) const
{
return *this - Fraction(d);
}
Fraction operator-(size_t s, const Fraction& f)
{
return Fraction(s * f.denom - f.num, f.denom);
}
Fraction operator-(double d, const Fraction& f)
{
return Fraction(d) - f;
}
Fraction Fraction::operator*(const Fraction& f) const
{
return Fraction(num * f.numerator(), denom * f.denominator());
}
Fraction Fraction::operator*(size_t s) const
{
return Fraction(num * s, denom);
}
Fraction Fraction::operator*(double d) const
{
return Fraction(num * d, denom);
}
Fraction operator*(size_t s, const Fraction& f)
{
return Fraction(f.numerator() * s, f.denominator());
}
Fraction operator*(double d, const Fraction& f)
{
return Fraction(f.numerator() * d, f.denominator());
}
Fraction Fraction::operator/(const Fraction& f) const
{
return (*this) * f.reciprocal();
}
Fraction Fraction::operator/(size_t s) const
{
return Fraction(num, denom * s);
}
Fraction Fraction::operator/(double d) const
{
return Fraction(num, denom * d);
}
Fraction operator/(size_t s, const Fraction& f)
{
return s * f.reciprocal();
}
Fraction operator/(double d, const Fraction& f)
{
return d * f.reciprocal();
}
Fraction Fraction::operator%(const Fraction& f) const
{
return ((*this) / f).value() > 0 ? Fraction((*this) - (floor(((*this) / f).value()) * f)) : Fraction((*this) - (ceil(((*this) / f).value()) * f));
}
Fraction Fraction::operator%(size_t s) const
{
return ((*this) / s).value() > 0 ? Fraction((*this) - (floor(((*this) / s).value()) * s)) : Fraction((*this) - (ceil(((*this) / s).value()) * s));
}
Fraction Fraction::operator%(double d) const
{
return ((*this) / d).value() > 0 ? Fraction((*this) - (floor(((*this) / d).value()) * d)) : Fraction((*this) - (ceil(((*this) / d).value()) * d));
}
size_t operator%(size_t s, const Fraction& f)
{
return (f / s).value() > 0 ? ((f) - (floor((s / f).value()) * f)).value() : ((f)-(ceil((s / f).value()) * f)).value();
}
double operator%(double d, const Fraction& f)
{
return (f / d).value() > 0 ? ((f)-(floor((d / f).value()) * f)).value() : ((f)-(ceil((d / f).value()) * f)).value();
}
Fraction& Fraction::operator+=(const Fraction& f)
{
*this = *this + f;
return *this;
}
Fraction& Fraction::operator+=(size_t s)
{
*this = *this + s;
return *this;
}
Fraction& Fraction::operator+=(double d)
{
*this = *this + d;
return *this;
}
size_t operator+=(size_t s, Fraction& f)
{
s += round(f.value());
return s;
}
double operator+=(double d, Fraction& f)
{
d += f.value();
return d;
}
Fraction& Fraction::operator-=(const Fraction& f)
{
*this = *this - f;
return *this;
}
Fraction& Fraction::operator-=(size_t s)
{
*this = *this - s;
return *this;
}
Fraction& Fraction::operator-=(double d)
{
*this = *this - d;
return *this;
}
size_t operator-=(size_t s, Fraction& f)
{
s -= round(f.value());
return s;
}
double operator-=(double d, Fraction& f)
{
d -= f.value();
return d;
}
Fraction& Fraction::operator*=(const Fraction& f)
{
*this = *this * f;
return *this;
}
Fraction& Fraction::operator*=(size_t s)
{
*this = *this * s;
return *this;
}
Fraction& Fraction::operator*=(double d)
{
*this = *this * d;
return *this;
}
size_t operator*=(size_t s, Fraction& f)
{
s *= round(f.value());
return s;
}
double operator*=(double d, Fraction& f)
{
d *= f.value();
return d;
}
Fraction& Fraction::operator/=(const Fraction& f)
{
*this = *this / f;
return *this;
}
Fraction& Fraction::operator/=(size_t s)
{
*this = *this / s;
return *this;
}
Fraction& Fraction::operator/=(double d)
{
*this = *this / d;
return *this;
}
size_t operator/=(size_t s, Fraction& f)
{
s /= round(f.value());
return s;
}
double operator/=(double d, Fraction& f)
{
d /= f.value();
return d;
}
Fraction& Fraction::operator%=(const Fraction& f)
{
*this = *this % f;
return *this;
}
Fraction& Fraction::operator%=(size_t s)
{
*this = *this % s;
return *this;
}
Fraction& Fraction::operator%=(double d)
{
*this = *this % d;
return *this;
}
size_t operator%=(size_t s, Fraction& f)
{
s = s % f;
return s;
}
double operator%=(double d, Fraction& f)
{
d = d % f;
return d;
}
Fraction& Fraction::operator++()
{
this->num += this->denom;
return *this;
}
Fraction Fraction::operator++(int)
{
Fraction copy{ *this };
this->num += this->denom;
return copy;
}
Fraction& Fraction::operator--()
{
this->num -= this->denom;
return *this;
}
Fraction Fraction::operator--(int)
{
Fraction copy{ *this };
this->num -= this->denom;
return copy;
}
Fraction Fraction::operator+()
{
return *this;
}
Fraction Fraction::operator-()
{
return Fraction(-num, denom);
}
long long Fraction::operator[](int i)
{
return i == 0 ? num : denom;
}
Most of the bottom ones are just operator overloads of different types as I was going to use the operators on Fraction objects, size_t and double objects. This should be more optimized as it has a simplify() function that is used and instead of functions like sum and difference, I used operator overloading. Fraction.str() is a bit more optimized than above. As for the zero division thing, I think that it will get caught and the compiler will at least issue a warning and when running, it should give a floating point error. If you found any bugs in the code, please comment below!