1

I have following problem. I wrote an class for rational numbers in c++. The class and the operators work fine, unless the numerator is bigger than the denominator.

I used for example -3/12 and 4/3 =13/12 but instead i get 3/4

The header file:

#ifndef _FRAC_
#define _FRAC_

#include <iostream>
#include <string>

class frac
{
private:
long numerator, denominator;
long gcd(long, long);
void reduce(const long, const long);
public:
frac(long z = 0, long n = 1);

const float frac::getq();
const std::string frac::getstr();
frac operator-() const
{
    return frac(-numerator, denominator);
}
frac& operator+=(const frac& a)
{
    numerator = a.numerator * denominator + numerator * a.denominator;
    denominator *= a.denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator-=(const frac& a)
{
    *this += -a;
    reduce(numerator, denominator);
    return *this;
}
frac& operator++() //Präfix
{
    numerator += denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator++(int empty) //Postfix
{
    numerator += denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator--() //Präfix
{
    numerator -= denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator--(int empty) //Postfix
{
    numerator -= denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator*=(const frac& a)
{
    numerator = a.numerator * numerator;
    denominator = a.denominator * denominator;
    reduce(numerator, denominator);
    return *this;
}
frac& operator/=(const frac& a)
{
    numerator = a.denominator * numerator;
    denominator = a.numerator * denominator;
    if (denominator < 0)
    {
        numerator = -numerator;
        denominator = -denominator;
    }
    reduce(numerator, denominator);
    return *this;
}
friend frac operator+ (const frac&, const frac&);
friend frac operator- (const frac&, const frac&);
friend frac operator* (const frac&, const frac&);
friend frac operator/ (const frac&, const frac&);

friend std::ostream& operator<< (std::ostream& os, const frac& a);
friend std::istream& operator>> (std::istream& is, frac& a);
};

#endif

the main.cpp

#include <iostream>
#include <sstream>
#include "FRAC.h"

using namespace std;

frac::frac(long z, long n)
{
if (n < 0)
{
    z = -z;
    n = -n;
}
numerator = z;
denominator = n;
}



const float frac::getq()
{
return static_cast<float>(numerator) / static_cast<float>(denominator);
}

const string frac::getstr()
{
reduce(numerator, denominator);
ostringstream z, n;
z << numerator;
n << denominator;
if (numerator == 0) 
    return "0";
else if (denominator == 1) 
    return z.str();
else if (numerator == denominator) 
    return "1";
else
    return z.str() + "/" + n.str();
}
//greatest common divisor
long frac::gcd(long z, long n)
{

z = abs(z);
n = abs(n);
if (n > z)
    return gcd(n, z);
else if (n != 0)
    return gcd(n, z % n);
else
    return z; 
}

void frac::reduce(const long z, const long n)
{
numerator /= gcd(z, n);
denominator /= gcd(z, n);
}

frac operator+(const frac& a, const frac& b)
{
frac temp;
temp.denominator = a.denominator * b.denominator;
temp.numerator = a.numerator * b.denominator + b.numerator * a.denominator;
temp.reduce(temp.numerator, temp.denominator);
return temp;
}

frac operator-(const frac& a, const frac& b)
{
frac temp = a;
temp += -b;
temp.reduce(temp.numerator, temp.denominator);
return temp;
}

frac operator*(const frac& a, const frac& b)
{
frac temp;
temp.numerator = a.numerator * b.numerator;
temp.denominator = a.denominator * b.denominator;
temp.reduce(temp.numerator, temp.denominator);
return temp;
}

frac operator/(const frac& a, const frac& b)
{
frac temp;
temp.numerator = a.numerator * b.denominator;
temp.denominator = a.denominator * b.numerator;
if (temp.denominator < 0)
{
    temp.numerator = -temp.numerator;
    temp.denominator = -temp.denominator;
}
temp.reduce(temp.numerator, temp.denominator);
return temp;
}

ostream& operator<<(ostream& os, const frac& a)
{
frac temp;
temp.numerator = a.numerator;
temp.denominator = a.denominator;
temp.reduce(temp.numerator, temp.denominator);
if (temp.numerator == 0) //intstead of 0/1 -> 0 
    os << "0";
else if (temp.denominator == 1) //instead of 3/1 -> 3 
    os << temp.numerator;
else if (temp.numerator == temp.denominator) //instead of 3/3 -> 1 
    os << "1";
else
    os << temp.numerator << "/" << temp.denominator;
return os;
}

istream& operator>>(istream& is, frac& a)
{
is >> a.numerator;
is >> a.denominator;
if (!is)
    return is;
if (a.denominator < 0)
{
    a.numerator = -a.numerator;
    a.denominator = -a.denominator;
}
return is;
}

// 
int main()
{
frac x(-3, 12), y(4 / 3), z;

z = x + y;
cout << z;
// i simply used that visual studio doesn't close the console
// z is 4/3 instead of 13/12
cin >> z;
return 0;
}

I assume that the problem is in operator+ method, the gcd function or in reduce...

I hope someone can help :)

Greetings and thanks

Thomas ^^

PeterFox
  • 19
  • 3

1 Answers1

0

The problem is with your test code:

frac x(-3, 12), y(4 / 3), z;

should be:

frac x(-3, 12), y(4, 3), z;

You are initialising y to 1 / 1, because 4 / 3 = 1 (integer division) and the default parameter for the denominator is 1.

-3/12 + 1 = 3/4

samgak
  • 23,944
  • 4
  • 60
  • 82