I am fairly new in C++ (I have spent all my life in C so I thought it's time to invest some time in learning a new language in order to enrich my knowledge :) ). I have a class named "Rational", I have all its specific functions for getters, setters, constructors, etc.(it's not relevant here). The interesting part is when I try to overload the +,-,,/ operators. I am able to successfully do this between two Rational objects, for example Rational a(1,5),b(5,5),c; c = a + b; so all this works just fine. Now I am trying to upgrade my class by trying to +,-,,/ between a Rational and an integer, for example 2 + a, 10 - b etc. Here is (a snippet of)my code for overloading between Rationals:
Rational.cc
...
Rational Rational::operator+(Rational B) {
int Num;
int Den;
Num = p * B.q + q * B.p;
Den = q * B.q;
Rational C(Num, Den);
C.simplifierFraction();
return C;
}
Rational Rational::operator-(Rational B) {
int Num;
int Den;
Num = p * B.q - q * B.p;
Den = q * B.q;
Rational C(Num, Den);
C.simplifierFraction();
return C;
}
Rational Rational::operator*(Rational B)
{
int Num;
int Den;
Num = p * B.p;
Den = q * B.q;
Rational C(Num, Den);
C.simplifierFraction();
return C;
}
Rational Rational::operator/(Rational B)
{
int Num;
int Den;
Rational invB = inverse(B);
Num = p * invB.p;
Den = q * invB.q;
Rational C(Num, Den);
C.simplifierFraction();
return C;
}
...
Rational.h
Rational operator+(Rational B);
Rational operator-(Rational B);
Rational operator*(Rational B);
Rational operator/(Rational B);
private:
int p;
int q;
protected:
TestRat.cc
int main() {
...
const Rational demi(1,2);
const Rational tiers(1,3);
const Rational quart(1,4);
r0 = demi + tiers - quart;
r1 = 1 + demi;
r2 = 2 - tiers;
r3 = 3 * quart;
r4 = 1 / r0;
...
So when I try to run TestRat.cc it says:
testrat.cc:31: error: no match for ‘operator+’ in ‘1 + r9’
testrat.cc:52: error: passing ‘const Rational’ as ‘this’ argument of ‘Rational Rational::operator+(Rational)’ discards qualifiers
testrat.cc:53: error: no match for ‘operator+’ in ‘1 + demi’
testrat.cc:54: error: no match for ‘operator-’ in ‘2 - tiers’
testrat.cc:55: error: no match for ‘operator*’ in ‘3 * quart’
testrat.cc:56: error: no match for ‘operator/’ in ‘1 / r0’
What must I do in order to be able to make this work?
Thanks!
tl;dr:
your operators should be declared as:
Rational operator+(const Rational& B) const;
well... these ones, at least. operator = should return a reference to *this, but that's outside the scope of this questions. Also, those operators are defined to work on Rational objects, whereas
r1 = 1 + demi;
attempts to operate on an int and a Rational object. You'll have to define outside the class an appropriate operator:
inline Rational operator+(int, const Rational& r)
{
//...
}
I suggest you start learning C++ with a good book though. Just picking up stuff from here and there isn't really going to work.
Related
I want to subtract two fractional numbers using operator overloading. I have write a piece of code in order to accomplish this task:
#include<iostream>
using namespace std;
void HCF(int& a, int& b)
{
int m, n;
m = a;
n = b;
while (m != n)
{
if (m > n)
m = m - n;
else
n = n - m;
}
a = a / m;
b = b / m;
}
class Rational {
int x1;
int y1;
public:
void simplify()
{
int m, n, r;
n = fabs(y1);
m = fabs(x1);
while (r = m % n)//Find the Maximum Common Number of m,n
{
m = n;
n = r;
}
y1 /= n; // Simplification
x1 /= n;
if (y1 < 0) // Convert denominator to positive number
{
y1 = -y1;
x1 = -x1;
}
}
Rational(int num = 0, int denom = 1)
{
if (denom) {
x1 = num;
y1 = denom;
}
else {
x1 = 0;
y1 = 1;
}
}
Rational(const Rational& copy)//Copy Constructor
{
x1 = copy.x1;
y1 = copy.y1;
}
Rational operator-(const Rational& x) const //Overloaded minus operator
{
Rational temp;
temp.x1 = x1 * x.y1 - x.x1 * y1;
temp.y1 = y1 * x.y1;
temp.simplify();
return temp;
}
operator string() const //Overloaded string operator
{
int numerator = x1, denominator = y1;
HCF(numerator, denominator);
string str;
if (denominator == 1)
str = to_string(numerator);
else
str = to_string(numerator) + "/" + to_string(denominator);
return str;
}
};
int main()
{
Rational a(5, 1);
Rational b(3, 4);
Rational c;
Rational d;
Rational x(5, 1);
c = a - x;
string expected1 = "0"; //Expected value
string actual1 = (string)c;//Actual value
cout << actual1.compare(expected1);//Comparing actual and expected value
d = c - b;
string expected2 = "-3/4";
string actual2 = (string)d;
cout << actual2.compare(expected2);
}
As we can see, in the main() function, both cout statements should print 0 because when we compare both strings, they must be equal. But the problem is, when I run this program, it prints nothing, and I don't know why.
My operator string() converts an integer fraction into a string. My operator- takes the LCM and finds the final value after subtracting two fractional numbers. In the main() function, I have declared five objects for class Rational, and then I simply perform subtraction and then I compare the expected and actual values, which should return 0 in the cout statement.
I have also used the simplify() member function to check whether the fraction is completely in simpler form or not. For example, it should simplify 2/4 into 1/2.
Where is the mistake? All other functions except operator- are running correctly. The real problem is with the operator-, ie when we perform c=a-x, the value of c would be 0 as a string. Similarly, if we perform d=c-b then the expected value should be -3/4 as a string.
I have also tried to run this code on Google Test, but it fails the test case.
Use this GCD (greatest common divisor) function to implement your HCF function. Yours currently exhibits an endless loop when given 0 as a first argument.
To reduce a fraction, divide numerator and denominator by their greatest common divisor.
This is called the Euclidean algorithm.
template <typename T>
T GCD(T a, T b) {
while (b != 0)
{
T t = a % b;
a = b;
b = t;
}
return std::max(a, -a);
}
I'm writing code that uses friend functions but I am not sure why I get the error "is a private member of" in the function "sum" since I declared the function as a friend in the header file.
Header File:
#include <iostream>
class rational
{
public:
// ToDo: Constructor that takes int numerator and int denominator
rational (int numerator = 0, int denominator = 1);
// ToDo: Member function to write a rational as n/d
void set (int set_numerator, int set_denominator);
// ToDo: declare an accessor function to get the numerator
int getNumerator () const;
// ToDo: declare an accessor function to get the denominator
int getDenominator () const;
// ToDo: declare a function called Sum that takes two rational objects
// sets the current object to the sum of the given objects using the
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
friend rational sum (const rational& r1, const rational& r2);
void output (std::ostream& out);
// member function to display the object
void input (std::istream& in);
private:
int numerator;
int denominator;
};
Source File:
#include <iostream>
using namespace std;
// takes two rational objects and uses the formula a/b + c/d = ( a*d + b*c)/(b*d) to change the numerator and denominator
rational sum (rational r1, rational r2)
{
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
cout << endl;
numerator = ((r2.denominator * r1.numerator) + (r1.denominator * r2.numerator));
denominator = (r1.denominator * r2.denominator);
}
rational sum (rational r1, rational r2) is a totally new function (no way to relate to the class rational) that accepts two rationals and returns a rational.
The correct way to implement the needed class method would be rational rational::sum (const rational& r1, const rational& r2)
Overall comment: Use capitalized first letter for classes (Rational)
You want something like this:
rational sum (const rational& r1, const rational& r2)
{
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
int numerator = ((r2.denominator * r1.numerator) + (r1.denominator * r2.numerator));
int denominator = (r1.denominator * r2.denominator);
return rational(numerator, denominator);
}
I want to compute the sum of two fraction using lcm of numerator and denominator. That means as a result I want to get a fraction in the reduced form. I have the following cpp file.
#include <iostream> //need it for cin and cout
#include "fraction.h"
Fraction::Fraction()
{
num = 1;
den = 1;
}
Fraction::Fraction(int n, int d)
{
int tmp_gcd = gcd(n, d);
num = n / tmp_gcd;
den = d / tmp_gcd;
}
int Fraction::gcd(int a, int b)
{
int tmp_gcd = 1;
// Implement GCD of two numbers;
return tmp_gcd;
}
int Fraction::lcm(int a, int b)
{
return a * b / gcd(a, b);
}
Fraction operator+(const Fraction&a,const Fraction &b)
{
int c=(lcm(b.den,a.den)/b.den)*a.num+b.num*(lcm(b.den,a.den)/a.den);
int d=lcm(b.den,a.den);
Fraction result(c,d);
return result;
}
However this code does not work because lcm is not defined in this scope.
What is the key that allows lcm work in this scope? If you please could explain more, I would be very thankful.
lcm is a member of Fraction. You can refer to it just as lcm within members of Fraction; but operator+ isn't a member, so you'll have to use the qualified name Fraction::lcm.
It will also need to be static. (Hopefully it already is, but I can't see the declaration to be sure).
I'm a beginner of c++. I want know why the exception is thrown at this line:
operator double() const
{
return this->denominator/this->numerator;
}
I found numerator == 0,but I have given default values in the ctor. Why? Please help me.
class Rational {
public:
int numerator;
int denominator;
Rational(int numerator = 2, int denominator = 1)
{
numerator = 2;
denominator = 1;
};
operator double() const
{
return this->denominator/this->numerator;
};
};
int main(int argc, const char * argv[])
{
Rational r(1, 2);
cout << r;
// double d = 0.5*r;
return 0;
}
First, this line is very wrong:
Rational(int numerator = 2, int denominator = 1){ numerator = 2; denominator = 1;};
The arguments numerator and denominator are in the stack frame of your ctor thus hiding your class's members Rational::numerator and Rational::denominator and secondly, you are completely ignoring what the caller actually sends as its arguments (not because you specify the default values, but because you explicitly set numerator=2; denominator=1. This line should actually be:
Rational(int numerator = 2, int denominator = 1){ this->numerator = numerator; this->denominator = denominator;};
OR you could use an initializer list (and overloaded constructors):
Rational() : numerator(2), denominator(1) {};
Rational(int numerator, int denominator) : numerator(numerator), denominator(denominator) {};
Now, the second problem is that int/int => int :: dividing an integer by another integer yields integer division, you need to cast one of your int's to double so that both int's are upconverted to double before calculating the division, like so:
operator double() const{ return ((double)this->denominator)/this->numerator;};
Rational(int numerator = 2, int denominator = 1)
{
numerator = 2;
denominator = 1;
};
I would change this to
Rational(int numerator, int denominator)
{
this->numerator = numerator;
this->denominator = denominator;
};
I don't know exactly if this is causing your problem, but I think it's contributing to it. Your call to Rational(int,int) will still work fine and add your specified values into the Object you're creating.
The issue with your code, is scope. I believe you were just re-assigning the arguments/parameters instead of actually re-assigning your instance variables, which I'm assuming was your goal.
I am trying to overload the += operator for my rational number class, but I don't believe that it's working because I always end up with the same result:
RationalNumber RationalNumber::operator+=(const RationalNumber &rhs){
int den = denominator * rhs.denominator;
int a = numerator * rhs.denominator;
int b = rhs.numerator * denominator;
int num = a+b;
RationalNumber ratNum(num, den);
return ratNum;
}
Inside main
//create two rational numbers
RationalNumber a(1, 3);
a.print();
RationalNumber b(6, 7);
b.print();
//test += operator
a+=(b);
a.print();
After calling a+=(b), a is still 1/3, it should be 25/21. Any ideas what I am doing wrong?
operator+= is supposed to modify the object itself and return a reference. You are instead creating a new object and returning that. Something like this might work (untested code):
RationalNumber &RationalNumber::operator+=(const RationalNumber &rhs){
int den = denominator * rhs.denominator;
int a = numerator * rhs.denominator;
int b = rhs.numerator * denominator;
int num = a+b;
numerator = num;
denominator = den;
return *this;
}
Likewise operator+ should return a new object and can almost always be implemented in terms of operator+=:
RationalNumber RationalNumber::operator+(const RationalNumber &rhs){
RationalNumber tmp(*this);
tmp += rhs;
return tmp;
}
Finally, (now i'm getting off topic) it is usually considered best practice to use free functions instead of members where you can for things like binary operators.
You are not changing the object the operator is applied to.
x += 3;
should change x.