> A rational number is the ratio of two integers (a numerator and a denominator) and is typically represented as a/b where

A rational number is the ratio of two integers (a numerator and a denominator) and is typically represented as a/b where

Posted at: 2014-12-18 
I'll give you a running start from some code I wrote a while back:

#define T rational

class T {

private:

? ? unsigned long long int numer, denom;

? ? bool sign;

protected:

? ? T( const bool s, const long long int &n, const long long int &d ) : sign( s ), numer( n ), denom( d ) { }

? ? static unsigned long long int gcd( unsigned long long int, unsigned long long int );

? ? T mulinv( ) const;

? ? T addinv( ) const;

public:

? ? T( ) : sign( true ), numer( 0 ), denom( 0 ) { }

? ? T( const T &n ) : sign( n.sign ), numer( n.numer ), denom( n.denom ) { }

? ? bool operator!=( const T &n ) const { return sign != n.sign || numer != n.numer || denom != n.denom; }

? ? bool operator==( const T &n ) const { return sign == n.sign && numer == n.numer && denom == n.denom; }

? ? static T strtonum( const char *, const char * );

? ? friend ostream & operator<<( ostream &, const T & );

? ? friend T operator+( const T &a, const T &b );

? ? friend T operator*( const T &a, const T &b );

? ? friend T operator-( const T &a, const T &b ) { return a + b.addinv( ); }

? ? friend T operator/( const T &a, const T &b ) { return a * b.mulinv( ); }

? ? friend T operator-( const T &n ) { return n.addinv( ); }

};

const T ERV;

const class S(ZERO) : public T { public: S(ZERO)( ) : T( false, 0, 1 ) { } } ZERO;

T T::mulinv( ) const {

? ? T result;

? ? if ( *this == ZERO || *this == ERV ) return ERV;

? ? result.sign= sign;

? ? result.numer= denom;

? ? result.denom= numer;

? ? return result;

}

T T::addinv( ) const {

? ? T result= *this;

? ? if ( result != ZERO && result != ERV ) result.sign= !result.sign;

? ? return result;

}

unsigned long long int T::gcd( unsigned long long int v1, unsigned long long int v2 ) {

? ? if ( v1 == 0 && v2 == 0 ) return 1;

? ? while ( v1 != 0 ) {

? ? ? ? unsigned long long int z= v1;

? ? ? ? v1= v2 % v1;

? ? ? ? v2= z;

? ? }

? ? return v2;

}

T operator+( const T &addend1, const T &addend2 ) {

? ? T result;

? ? unsigned long long int a, b, f, g;

? ? if ( addend1 == ERV || addend2 == ERV ) return ERV;

? ? f= T::gcd( addend1.denom, addend2.denom );

? ? a= addend1.denom / f;

? ? b= addend2.denom / f;

? ? result.denom= a * addend2.denom;

? ? f= b * addend1.numer;

? ? g= a * addend2.numer;

? ? if ( !addend1.sign && !addend2.sign ) {

? ? ? ? result.numer= f + g;

? ? ? ? result.sign= false;

? ? } else if ( !addend1.sign && addend2.sign ) {

? ? ? ? if ( f >= g ) {

? ? ? ? ? ? result.numer= f - g;

? ? ? ? ? ? result.sign= false;

? ? ? ? } else {

? ? ? ? ? ? result.numer= g - f;

? ? ? ? ? ? result.sign= true;

? ? ? ? }

? ? } else if ( addend1.sign && !addend2.sign ) {

? ? ? ? if ( g >= f ) {

? ? ? ? ? ? result.numer= g - f;

? ? ? ? ? ? result.sign= false;

? ? ? ? } else {

? ? ? ? ? ? result.numer= f - g;

? ? ? ? ? ? result.sign= true;

? ? ? ? }

? ? } else {

? ? ? ? result.numer= f + g;

? ? ? ? result.sign= true;

? ? }

? ? f= T::gcd( result.numer, result.denom );

? ? result.numer /= f;

? ? result.denom /= f;

? ? if ( result.numer == 0 ) result.sign= false;

? ? return result;

}

T operator*( const T &multiplicand1, const T &multiplicand2 ) {

? ? T result;

? ? unsigned long long int a, b, f, g;

? ? if ( multiplicand1 == ERV || multiplicand2 == ERV ) return ERV;

? ? a= T::gcd( multiplicand1.numer, multiplicand2.denom );

? ? f= multiplicand1.numer / a;

? ? g= multiplicand2.denom / a;

? ? b= T::gcd( multiplicand1.denom, multiplicand2.numer );

? ? a= multiplicand1.denom / b;

? ? b= multiplicand2.numer / b;

? ? result.numer= f * b;

? ? result.denom= a * g;

? ? result.sign= ?multiplicand1.sign ^ multiplicand2.sign;

? ? if ( result.numer == 0 ) result.sign= false;

? ? return result;

}

T T::strtonum( const char *a, const char *b ) {

? ? char *s= new char[b-a+1];

? ? strncpy( s, a, b-a );

? ? s[b-a]= '\0';

? ? T v( false, 0, 1 );

? ? size_t decimals;

? ? char *e, *f;

? ? if ( *s == '-' ) {

? ? ? ? v.numer= strtoul( s+1, &e, 10 );

? ? ? ? v.sign= true;

? ? } else

? ? ? ? v.numer= strtoul( s, &e, 10 );

? ? if ( *(f= e) == '.' ) {

? ? ? ? v.denom= strtoul( ++e, &f, 10 );

? ? ? ? decimals= f - e;

? ? ? ? if ( decimals > 0 ) {

? ? ? ? ? ? unsigned long long int c= 1;

? ? ? ? ? ? do c *= 10; while ( --decimals > 0 );

? ? ? ? ? ? v.numer= v.numer*c + v.denom;

? ? ? ? ? ? v.denom= c;

? ? ? ? ? ? c= gcd( v.numer, v.denom );

? ? ? ? ? ? v.numer /= c;

? ? ? ? ? ? v.denom /= c;

? ? ? ? }

? ? }

? ? if ( *(e= f) == 'E' || *e == 'e' ) {

? ? ? ? long int exp= strtol( ++e, &f, 10 );

? ? ? ? for ( ; exp > 0; --exp ) {

? ? ? ? ? ? unsigned long long int a= gcd( 10, v.denom );

? ? ? ? ? ? v.numer *= 10 / a;

? ? ? ? ? ? v.denom /= a;

? ? ? ? }

? ? ? ? for ( ; exp < 0; ++exp ) {

? ? ? ? ? ? unsigned long long int a= gcd( 10, v.numer );

? ? ? ? ? ? v.numer /= a;

? ? ? ? ? ? v.denom *= 10 / a;

? ? ? ? }

? ? }

? ? delete[] s;

? ? return v;

}

ostream & operator<<( ostream &fout, const T &n ) {

? ? if ( n != ERV ) {

? ? ? ? cout << (n.sign? "-":"") << n.numer;

? ? ? ? if ( n.denom != 1 ) cout << "/" << n.denom;

? ? ? ? cout << " " << (n.sign? -1.0:1.0)*n.numer / (double) n.denom;

? ? } else

? ? ? ? cout << "ERR";

? ? return fout;

}

A rational number is the ration of two integers (a numerator and a denominator) and is typically represented as a/b where a and b are integers. Whole integers such as 6 would be represented with 1 in the denominator. A reduced form representation is one where the greatest common divisor of a and b is 1. That is, 2/3 is a reduced form representation but 10/15 is not.

Write a class called Rational which has instance variables num and den which hold the numerator and denominator values such that the number is always expressed in reduced form. Include the following methods in the class Rational:

(a) A constructor that accepts two integer parameters a and b and creates a Rational object representing the rational number a/b.

(b) A constructor that accepts one integer parameter a and creates a Rational object representing the rational number a.

(c) A method called setRational which accepts two integer parameters a and b and sets the number to a/b.

(d) A method called setRational which accepts one integer parameter a and sets the number to a.

(e) A method called getNum that returns the numerator in reduced form expression of rational number.

(f) A method called getDen that returns the den in the reduced form expression of the rational no.

(g) A method called add which accepts two integers as parameters (say, c and d) and updates num (say, holding value a) and den (say, holding value b) such that num/den = a/b + c/d. The final stored value of num and den should be in reduces form.