In: Computer Science
Task CPP
Create a class called Mixed. Objects of type Mixed will store and manage rational numbers in a mixed number format (integer part and a fraction part). The class, along with the required operator overloads, should be written in the files mixed.h and mixed.cpp.
Details and Requirements
Finish Lab 2 by creating a Mixed class definition with constructor functions and some methods.
The Mixed class should have public member functions Evaluate(), ToFraction(), and Simplify(). The Evaluate() function should return a double, the others don’t return anything. These functions have no parameters. The names must match the ones here exactly. They should do the following:
Create an overload of the extraction operator >> for reading mixed numbers from an input stream. The input format for a Mixed number object will be:
integer numerator/denominator
i.e. the integer part, a space, and the fraction part (in numerator/denominator form), where the integer, numerator, and denominator parts are all of type int. You may assume that this will always be the format that is entered (i.e. your function does not have to handle entry of incorrect types that would violate this format). However, this function should check the values that come in. In the case of an incorrect entry, just set the Mixed object to represent the number 0, as a default. An incorrect entry occurs if a denominator value of 0 is entered, or if an improper placement of a negative sign is used. Valid entry of a negative number should follow this rule - if the integer part is non-zero, the negative sign is entered on the integer part; if the integer part is 0, the negative sign is entered on the numerator part (and therefore the negative sign should never be in the denominator). Examples:
Valid inputs: 2 7/3 , -5 2/7 , 4 0/7 , 0 2/5 , 0 -8/3
Invalid inputs: 2 4/0 , -2 -4/5 , 3 -6/3 , 0 2/-3
Create an overload of the insertion operator << for output of Mixed numbers. This should output the mixed number in the same format as above, with the following exceptions: If the object represents a 0, then just display a 0. Otherwise: If the integer part is 0, do not display it. If the fraction part equals 0, do not display it. For negative numbers, the minus sign is always displayed to the left.
Examples: 0 , 2 , -5 , 3/4 , -6/7 , -2 4/5 , 7 2/3
Create operator overloads for the 4 standard arithmetic operations ( + , - , * , / ) , to perform addition, subtraction, multiplication, and division of two mixed numbers. Each of these operators will perform its task on two Mixed objects as operands and will return a Mixed object as a result - using the usual meaning of arithmetic operations on rational numbers. Also, each of these operators should return their result in simplified form. (e.g. return 3 2/3 instead of 3 10/15, for example).
Use function __gcd (you need to add #include <algorithm>) for calculation of the greatest common divisor) for simplification of the fractions. For subtraction and division, you can use inverse rules to simplify your code, see Inverse of rational number.
In the division operator, if the second operand is 0, this would yield an invalid result. Since we have to return something from the operator, return 0 as a default (even though there is no valid answer in this case). Example:
Mixed m(1, 2, 3); // value is 1 2/3 Mixed z; // value is 0 Mixed r = m / z; // r is 0 (even though this is not good math)
Create overloads for the increment and decrement operators (++ and –). You need to handle both the pre- and post- forms (pre-increment, post-increment, pre-decrement, post-decrement). These operators should have their usual meaning – increment will add 1 to the Mixed value, decrement will subtract 1. Example:
Mixed m1(1, 2, 3); // 1 2/3 Mixed m2(2, 1, 2); // 2 1/2 cout << m1++; // prints 1 2/3, m1 is now 2 2/3 cout << ++m1; // prints 3 2/3, m1 is now 3 2/3 cout << m2--; // prints 2 1/2, m2 is now 1 1/2 cout << --m2; // prints 1/2 , m2 is now 0 1/2
Driver Program
The sample driver program that is provided can be found below. Note, this is not a comprehensive set of tests. It is just some code to get you started, illustrating some sample calls.
#include <iostream>
#include "mixed.h"
using namespace std;
int main(){
Mixed m0(1, 1, 1); // 1 1/1 == 2
m0.Simplify();
cout << m0 << endl; // prints 2
m0.ToFraction();
cout << m0 << endl; // prints 2/1
Mixed m1(1, 2, 3); // 1 2/3
m1.Print(); // prints 1 2/3
cout << m1++ << endl; // prints 1 2/3, m1 is now 2
2/3
cout << ++m1 << endl; // prints 3 2/3, m1 is now 3
2/3
Mixed m2(2, 5, 3); // 2 5/3
cout << m2 << endl; // prints 2 5/3
cout << m2.Evaluate() << endl; // prints 3.6666
m2.Simplify(); // m2 is now 3 2/3
cout << m2 << endl; // prints 3 2/3
Mixed m3 = m1 + m2; // m3 is now 7 1/3
cout << m3 << endl; // prints 7 1/3
cout << m3.Evaluate() << endl; // prints 7.3333
Mixed m4(1, 2, 3); // 1 2/3
m4.ToFraction();
cout << m4 << endl; // prints 5/3
Mixed m5 = m4 + Mixed(1);
cout << m5 << endl; // prints 2 2/3
Mixed m6(1);
cout << m6 << endl; // prints 1
m6.ToFraction();
cout << m6 << endl; // prints 1/1
cout << m6-m4 << endl; // prints -2/3
Mixed m7(0,3,4);
cout << m5*m7 << endl; // prints 2 (= 8/3 * 3/4)
cout << m5/m7 << endl; // prints 3 5/9 (32/9 = 8/3 *
4/3)
cout << "m4 == m4: " << boolalpha << (m4 == m4)
<< endl;
cout << "m5 != m4: " << boolalpha << (m5 != m4)
<< endl;
cout << "m5 > m4: " << boolalpha << (m5 >
m4) << endl;
cout << "m5 >= m4: " << boolalpha << (m5 >=
m4) << endl;
cout << "m4 < m5: " << boolalpha << (m4 <
m5) << endl;
cout << "m4 <= m4: " << boolalpha << (m4 <=
m4) << endl;
}
// mixed.h
#ifndef MIXED_H_INCLUDED
#define MIXED_H_INCLUDED
#include <iostream>
using namespace std;
class Mixed
{
private :
int whole, numerator, denominator;
void validate();
public:
Mixed(int w, int num, int den);
Mixed(int w=0);
double Evaluate() const;
void ToFraction();
void Simplify();
void Print();
friend istream& operator>>(istream& in, Mixed&
m);
friend ostream& operator<<(ostream& out, const
Mixed& m);
bool operator<(const Mixed& m);
bool operator>(const Mixed& m);
bool operator<=(const Mixed& m);
bool operator>=(const Mixed& m);
bool operator==(const Mixed& m);
bool operator!=(const Mixed& m);
Mixed operator+(const Mixed& m) const;
Mixed operator-(const Mixed& m) const;
Mixed operator*(const Mixed& m) const;
Mixed operator/(const Mixed& m) const;
Mixed& operator++();
Mixed operator++(int x);
Mixed& operator--();
Mixed operator--(int x);
};
#endif // MIXED_H_INCLUDED
//end of mixed.h
// mixed.cpp
#include "mixed.h"
#include <cmath>
#include <algorithm>
// constructors
Mixed::Mixed(int w, int num, int den)
{
whole = w;
numerator = num;
denominator = den;
validate();
}
// helper function to validate the fraction
void Mixed:: validate()
{
if(whole == 0)
{
if((numerator < 0 && denominator < 0) || (numerator
> 0 && denominator < 0))
{
whole = 0;
numerator = 0;
denominator = 1;
}
}else
{
if(numerator < 0 || denominator < 0)
{
whole = 0;
numerator = 0;
denominator = 1;
}
}
}
Mixed::Mixed(int w)
{
whole = w;
numerator = 0;
denominator = 1;
}
// function to evaluate the fraction and return the value as
double
double Mixed:: Evaluate() const
{
bool negative = false;
if(whole < 0 || numerator < 0)
negative = true;
double val =
((double)((abs(whole)*abs(denominator))+abs(numerator)))/abs(denominator);
if(negative)
return -val;
return val;
}
// function to convert mixed to improper fraction
void Mixed:: ToFraction()
{
bool negative = false;
if(whole < 0 || numerator < 0)
negative = true;
numerator = abs(whole)*abs(denominator)+abs(numerator);
whole = 0;
if(negative)
numerator = -numerator;
}
// function to simplify the fraction
void Mixed::Simplify()
{
// convert it to improper fraction
ToFraction();
int gcd = __gcd(abs(numerator), abs(denominator)); // get the gcd of absolute value of numerator and denominator
// gcd is not 0
if(gcd != 0)
{
// divide numerator and denominator by gcd
numerator /= gcd;
denominator /= gcd;
}
// set if fraction is negative
bool negative = false;
if(numerator < 0)
negative = true;
// get the whole part
whole = numerator/denominator;
// get the numerator
numerator = abs(numerator) - abs(whole)*denominator;
// if whole is 0 and fraction is negative, negate the
numerator
if(whole == 0 && negative)
numerator = -numerator;
}
void Mixed:: Print()
{
if(whole == 0)
{
if(numerator == 0)
cout<<"0";
else
cout<<numerator<<"/"<<denominator;
}else
{
if(numerator == 0)
cout<<whole;
else
cout<<whole<<"
"<<numerator<<"/"<<denominator;
}
cout<<endl;
}
// overloaded extraction operator
istream& operator>>(istream& in, Mixed& m)
{
char sep;
in>>m.whole>>m.numerator>>sep>>m.denominator;
m.validate();
return in;
}
// overloaded insertion operator
ostream& operator<<(ostream& out, const Mixed&
m)
{
if(m.whole == 0)
{
if(m.numerator == 0)
out<<"0";
else
out<<m.numerator<<"/"<<m.denominator;
}else
{
if(m.numerator == 0 )
out<<m.whole;
else
out<<m.whole<<"
"<<m.numerator<<"/"<<m.denominator;
}
return out;
}
// comparison operators
bool Mixed::operator<(const Mixed& m)
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fraction
m1.ToFraction();
m2.ToFraction();
return((m1.numerator*m2.denominator) <
(m2.numerator*m1.denominator));
}
bool Mixed:: operator>(const Mixed& m)
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fraction
m1.ToFraction();
m2.ToFraction();
return((m1.numerator*m2.denominator) >
(m2.numerator*m1.denominator));
}
bool Mixed:: operator<=(const Mixed& m)
{
return((*this < m) || (*this == m));
}
bool Mixed:: operator>=(const Mixed& m)
{
return((*this > m) || (*this == m));
}
bool Mixed:: operator==(const Mixed& m)
{
return(whole == m.whole && numerator == m.numerator
&& denominator == m.denominator );
}
bool Mixed:: operator!=(const Mixed& m)
{
return !(*this == m);
}
// arithmetic operators
Mixed Mixed:: operator+(const Mixed& m) const
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fractions
m1.ToFraction();
m2.ToFraction();
// compute numerator and denominator
int num =
(m1.numerator*m2.denominator)+(m2.numerator*m1.denominator);
int den = (m1.denominator*m2.denominator);
// create the resultant Mixed fraction
Mixed result(0, num, den);
result.Simplify(); // simplify the fraction
return result;
}
Mixed Mixed:: operator-(const Mixed& m) const
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fractions
m1.ToFraction();
m2.ToFraction();
// compute numerator and denominator
int num =
(m1.numerator*m2.denominator)-(m2.numerator*m1.denominator);
int den = (m1.denominator*m2.denominator);
// create the resultant Mixed fraction
Mixed result(0, num, den);
result.Simplify(); // simplify the fraction
return result;
}
Mixed Mixed:: operator*(const Mixed& m) const
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fractions
m1.ToFraction();
m2.ToFraction();
// compute numerator and denominator
int num = (m1.numerator*m2.numerator);
int den = (m1.denominator*m2.denominator);
// create the resultant Mixed fraction
Mixed result(0, num, den);
result.Simplify(); // simplify the fraction
return result;
}
Mixed Mixed:: operator/(const Mixed& m) const
{
// create 2 fractions from this and m
Mixed m1(whole, numerator, denominator);
Mixed m2(m.whole, m.numerator, m.denominator);
// convert them to improper fractions
m1.ToFraction();
m2.ToFraction();
// compute numerator and denominator
int num = (m1.numerator*m2.denominator);
int den = (m2.numerator*m1.denominator);
// create the resultant Mixed fraction
Mixed result(0, num, den);
result.Simplify(); // simplify the fraction
return result;
}
// increment and decrement operators
Mixed& Mixed:: operator++()
{
++whole; // increment the whole part
return *this;
}
Mixed Mixed:: operator++(int x)
{
Mixed temp = *this; // set temp to this
++*this; // increment this
return temp; // return the old this i.e temp
}
Mixed& Mixed:: operator--()
{
--whole; // decrement the whole part
return *this;
}
Mixed Mixed:: operator--(int x)
{
Mixed temp = *this; // set temp to this
--*this; // decrement this
return temp; // return the old this i.e temp
}
//end of mixed.cpp
// main.cpp
#include <iostream>
#include "mixed.h"
using namespace std;
int main()
{
Mixed m0(1, 1, 1); // 1 1/1 == 2
m0.Simplify();
cout << m0 << endl; // prints 2
m0.ToFraction();
cout << m0 << endl; // prints 2/1
Mixed m1(1, 2, 3); // 1 2/3
m1.Print(); // prints 1 2/3
cout << m1++ << endl; // prints 1 2/3, m1 is now 2
2/3
cout << ++m1 << endl; // prints 3 2/3, m1 is now 3
2/3
Mixed m2(2, 5, 3); // 2 5/3
cout << m2 << endl; // prints 2 5/3
cout << m2.Evaluate() << endl; // prints 3.6666
m2.Simplify(); // m2 is now 3 2/3
cout << m2 << endl; // prints 3 2/3
Mixed m3 = m1 + m2; // m3 is now 7 1/3
cout << m3 << endl; // prints 7 1/3
cout << m3.Evaluate() << endl; // prints 7.3333
Mixed m4(1, 2, 3); // 1 2/3
m4.ToFraction();
cout << m4 << endl; // prints 5/3
Mixed m5 = m4 + Mixed(1);
cout << m5 << endl; // prints 2 2/3
Mixed m6(1);
cout << m6 << endl; // prints 1
m6.ToFraction();
cout << m6 << endl; // prints 1/1
cout << m6-m4 << endl; // prints -2/3
Mixed m7(0,3,4);
cout << m5*m7 << endl; // prints 2 (= 8/3 * 3/4)
cout << m5/m7 << endl; // prints 3 5/9 (32/9 = 8/3 *
4/3)
cout << "m4 == m4: " << boolalpha << (m4 == m4)
<< endl;
cout << "m5 != m4: " << boolalpha << (m5 != m4)
<< endl;
cout << "m5 > m4: " << boolalpha << (m5 >
m4) << endl;
cout << "m5 >= m4: " << boolalpha << (m5 >=
m4) << endl;
cout << "m4 < m5: " << boolalpha << (m4 <
m5) << endl;
cout << "m4 <= m4: " << boolalpha << (m4 <=
m4) << endl;
return 0;
}
//end of main.cpp
Output: