// Class implementation file: fraction.cc #include #include // this is needed for the abs function #include "mymath.h" #include "fraction.h" using namespace std; // Implementation section //********************************************* // default constructor; creats 0/1 //********************************************* fraction::fraction() { numer = 0; denom = 1; } //********************************************* // constructor to create num/1. // // num imports the numerator to use //********************************************* fraction::fraction(int num) { numer = num ; denom = 1; } //********************************************* // constructor to create num/den. If default values are used, this is the // only implementation required // // num imports the numerator to use // den imports the denominator to use // // pre-condition -- den is not 0 //********************************************* fraction::fraction(int num, int den) { assert(den != 0); // denominator of 0 is invalid so crash numer = num ; denom = den; reduce(); // ensure denominator is positive and fraction reduced } //******************************************************************* // method to add this fraction and the argument and return the result // // frac -- imports the fraction to add to this one //******************************************************************* fraction fraction::add(const fraction& frac) const { fraction sum; sum.denom = lcm(denom, frac.denom); sum.numer = numer * (sum.denom / denom) + frac.numer * (sum.denom /frac.denom); sum.reduce(); return sum; } //************************************************************************** // method to subtract the argument from this fraction and return the result // // frac -- imports the fraction to subtract from this one //************************************************************************** fraction fraction::sub(const fraction& frac) const { fraction diff; diff.denom = lcm(denom, frac.denom); diff.numer = numer * (diff.denom / denom) - frac.numer * (diff.denom /frac.denom); diff.reduce(); return diff; } //************************************************************************** // method to multiply this fraction and the argument and return the result // // frac -- imports the fraction to multiply by //************************************************************************** fraction fraction::mult(const fraction& frac) const { int num = numer * frac.numer; int den = denom * frac.denom; fraction prod(num, den); return prod; } //************************************************************************** // method to divide this fraction by the argument and return the result // // frac -- imports the fraction to divide by // // pre-condition -- frac is not 0 //************************************************************************** fraction fraction::div(const fraction& frac) const { assert (frac.numer != 0); return mult(frac.reciprocal()); } //************************************************************************** // method to return the reciprocal of this fraction // // pre-condition -- this fraction is not 0 //************************************************************************** fraction fraction::reciprocal() const { assert (numer != 0); return fraction(denom, numer); } //******************************************************************* // method to return the numerator //******************************************************************* int fraction::num() const { return numer; } //******************************************************************* // method to return the denominator //******************************************************************* int fraction::den() const { return denom; } //************************************************************************** // method to compare the argument to this fraction and return true if they // are the same // // frac -- imports the fraction to compare to this one //************************************************************************** bool fraction::sameAs(const fraction& frac) const { return numer == frac.numer && denom == frac.denom; } //************************************************************************** // method to compare the argument to this fraction and return true if this // fraction is less than the argument // // frac -- imports the fraction to compare to this one //************************************************************************** bool fraction::isLessThan(const fraction& frac) const { // convert to common denominator and compare the numerators int comDivisor = gcd(denom, frac.denom); return (numer * (frac.denom / comDivisor) < frac.numer * (denom / comDivisor) ); } //*********************************************************************** // private helper function to reduce fraction // // post-condition -- the fraction is reduced to lowest terms and the // denominator is positive //*********************************************************************** void fraction::reduce() { if (denom < 0) { // ensure that denominator is always positive numer = -numer; denom = -denom; } // gcd must have positive ints so send absolute value of numerator int comDivisor = gcd(abs(numer), denom); numer /= comDivisor; denom /= comDivisor; } //*************************************************** // method to print a fraction // // oStr -- imports the stream to insert it into and // exports the updated stream //*************************************************** void fraction::print(ostream &oStr) const { oStr << numer; if (numer != 0 && denom != 1) // only print / and denominator oStr << "/" << denom; // if the fraction is not 0 and // the denominator is not 1 } //********************************************************** // method to print a fraction as a mixed number if necessary // // oStr -- imports the stream to insert it into and // exports the updated stream //********************************************************** void fraction::printMixed(ostream &oStr) const { if (numer < 0) oStr << '-'; // handle the possible negative int temp = abs(numer); if (temp < denom || denom == 1) // proper fraction so just print it print(oStr); else // improper fraction print as mixed oStr << temp/denom << '&' << temp%denom << '/' << denom; } //********************************************************************** // method to read a fraction. // // iStr -- imports the stream to extract the fraction from and // exports the updated stream // // post-condition -- if the data entered was valid, the fraction will be // set to it and reduced. If data entered is not valid // the value of the fraction is undefined and iStr will // have the error flag set. //*********************************************************************** void fraction::read(istream &iStr) { iStr >> numer; if (!iStr.good()) return; // error so return with error state if (iStr.peek() != '/') // no slash coming so no denominator denom = 1; // so set denominator to 1 else { // otherwise iStr.ignore(); // ignore the slash iStr >> denom; // get the denominator if (!iStr.good()) return; // error so return with error state if (denom == 0) { // denominator is 0 iStr.clear(ios::badbit); // set bad bit -- data lost return; // return with error state set } } // we have a valid fraction so reduce it reduce(); }