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.
Related
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 apologize if the question is Naive.
I am trying to overload the addition operator for fractions. My intent was to add fractions but for some reason it is adding the integers. Can some one explain why is it performing the integer addition. Code is below.
#include <iostream>
#include <string>
using namespace std;
class Fraction{
long numerator;
long denominator;
long gcd(long num1, long num2);
long lcm(long num1, long num2);
public:
void convert_int_to_fraction(int num);
void reduce();
Fraction(int num);
Fraction(){
numerator = 0;
denominator = 0;
}
Fraction(long num, long den);
Fraction operator+(Fraction fraction);
friend ostream& operator<<(ostream& os, const Fraction& fracNumber);
};
void Fraction::convert_int_to_fraction(int num){
denominator = 1;
numerator = long(num);
reduce();
}
Fraction::Fraction(int num){
convert_int_to_fraction(num);
}
long Fraction::gcd(long num1, long num2){
if(num1 == 0)
return num2;
else
return (gcd(num2 % num1, num1));
}
//Math function to calculate LCM
long Fraction::lcm(long num1, long num2){
long great_Divisor = gcd(num1, num2);
return ((num1/great_Divisor) * num2);
}
//Reduce fraction to its minimal
void Fraction::reduce(){
if(denominator!=0){
long great_Divisor = gcd(numerator, denominator);
numerator /= great_Divisor;
denominator /= great_Divisor;
if(denominator < 0 && numerator > 0){
denominator = -denominator;
numerator = -numerator;
}
}
}
Fraction::Fraction(long num, long den):numerator(num), denominator(den){
reduce();
}
ostream& operator<<(ostream& os, const Fraction& fracNumber){
os << fracNumber.numerator << "/" << fracNumber.denominator ;
return os;
}
Fraction Fraction::operator+(Fraction fraction){
Fraction result;
long least_Multiple = lcm(denominator, fraction.denominator);
result.denominator = (least_Multiple);
long result_Numerator = ((numerator * (least_Multiple/denominator)) +
(fraction.numerator * (least_Multiple/fraction.denominator)));
result.numerator = (result_Numerator);
result.reduce();
return result;
}
int main(){
Fraction frac1(2,4);
cout << frac1 + 2 << endl;
return 0;
}
The output is 5/2 So I tried to do it the other way round
cout << 2 + frac1 << endl;
This is giving me error. So now I tried to fix this by implementing these two functions.
Fraction::operator int(){
return convert_fraction_to_int();
}
int Fraction::convert_fraction_to_int(){
return ((int)(numerator/denominator));
}
Now even the first operation cout doesnt work. But the best thing is everything works fine when I typecast the variables. Can anyone explain why it is working in the first case, why not in the second case and why broken in the third case.
.My intent was to add fractions but for some reason it is adding the integers. Can some one explain why is it performing the integer addition.
There is a converting constructor from int to Fraction.
frac1 + 2 is being converted to frac1 + Fraction(2) by the compiler.
Update
If you want the compiler to be able support both frac1 + 2 and 2 + frac1, you can make the operator+ function a non-member function.
friend Fraction operator+(Fraction const& lhs, Fraction const& rhs);
and implement it as:
Fraction operator+(Fraction const& lhs, Fraction const& rhs)
{
Fraction result;
// Needed to make lcm and gcd static member functions since
// they work independent of the member variables.
long least_Multiple = Fraction::lcm(lhs.denominator, rhs.denominator);
result.denominator = (least_Multiple);
long result_Numerator = ((lhs.numerator * (least_Multiple/lhs.denominator)) +
(rhs.numerator * (least_Multiple/rhs.denominator)));
result.numerator = (result_Numerator);
result.reduce();
return result;
}
Now, you can use
Fraction frac1(2,4);
Fraction frac2(3,7);
cout << frac1 + 2 << endl;
cout << 3 + frac1 << endl;
cout << frac1 + frac2 << endl;
I made a class that can add, multiply and divide fractions which is presented below
class fraction
{
unsigned long long num, denom;
public:
fraction(int n, int d): num{n}, denom{d} {};
fraction& operator+=(fraction frac);
fraction& operator*=(fraction frac);
fraction& operator/=(fraction frac);
friend ostream& operator<<(ostream& os, const fraction& frac);
};
fraction& fraction::operator+=(fraction frac)
{
unsigned long long least_mult = lcm(denom, frac.denom); // Least-Common Multiple
num *= least_mult/denom;
num += frac.num*least_mult/frac.denom,
denom = least_mult;
return *this;
}
fraction& fraction::operator*=(fraction frac)
{
num *= frac.num;
denom *= frac.denom;
return *this;
}
fraction& fraction::operator/=(fraction frac)
{
num *= frac.denom;
denom *= frac.num;
return *this;
}
ostream& operator<<(ostream& os, const fraction& frac)
{
os << frac.num << '/' << frac.denom;
return os;
}
fraction operator+(fraction a, fraction b) {return a+=b;}
fraction operator*(fraction a, fraction b) {return a*=b;}
fraction operator/(fraction a, fraction b) {return a/=b;
}
When I try to compute square root two convergence using sqrt_two = 1 + 1/(1+sqrt_two) recursive relation when I get up to 4478554083/3166815962, the next value is 8399386631/7645270045 which is totally off as it is about 1.098, and therefore all the subsequent values are wrong too.
int main()
{
fraction one(1, 1), sqrt_two(3,2);
for(int i = 1; i < 50; ++i)
{
sqrt_two = one + one/(one+sqrt_two);
cout << sqrt_two << endl;
}
return 0;
}
I have tried 1+1/(1+8399386631/7645270045)) manually on a calculator and the result is still a square root convergent.
Looking at your code, there are lines that are susceptible to overflow. Perhaps one has happened in this case. For example,
num += frac.num*least_mult/frac.denom,
(which looks like it contains a typo, incidentally).
So, I'd suggest you see how to check for overflow, and then somehow incorporate it into your class. I'm not sure what you should do in such a case, though.
To compute the step that gives bad results you multiply two numbers of about 32 bits. The result exceeds the long long size (64 bit if unsigned) and you end up having wrong result because of overflow. A calculator (using more bits or silently converting to floating point) overcomes this problem.
I have written the following class for modifying a Fraction object.
#include "Fraction.h"
#include "GCD.h"
#include <iostream>
using std::cout;
//Implementation of the timesEq() member function
//Performs similar operation as the *= operator on the built-in types
const Fraction & Fraction::timesEq(const Fraction & op )
{
numerator *= op.numerator;
denominator *= op.denominator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::plusEq (const Fraction & op )
{
numerator *= op.denominator;
numerator += op.numerator * denominator;
denominator *= op.denominator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::minusEq (const Fraction & op )
{
numerator *= op.denominator;
denominator = denominator * op.denominator;
numerator -= op.numerator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
const Fraction & Fraction::divideEq (const Fraction & op )
{
numerator *= op.denominator;
denominator *= op.numerator;
simplify(); // will make sure that denominator is positive and
// will invoke gcd() function to reduce fraction
// as much as possible
return (*this); // returns the object which invoked the method
}
Fraction Fraction::negate(void) const
{
return (*this * -1);
}
void Fraction::display(void)const {
cout << numerator << "/" << denominator;
}
void Fraction::simplify(void)
{
gcd = gcd(numerator, denominator);
numerator /= gcd;
denominator /= gcd;
}
But am having trouble with the negate function.
I am using the function like so: B = A.negate(), and as such, I cannot modify the original A object, but need to assign the negated object to B.
Right now the implementation I have is giving an error:
Error: no operator "*" matches these operands
operand types are: const Fraction * int
I'm not sure what I am doing wrong. What needs to be changed?
Assuming you have a constructor that takes two ints as arguments (if you don't, you should, and not just for the sake of my answer), do this:
return Fraction(-numerator, denominator);
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.