Question

In: Computer Science

Lab Assignment Objectives 'Be able to overload combined binary operators as member operator functions. Show how...

Lab Assignment Objectives

  1. 'Be able to overload combined binary operators as member operator functions.
  2. Show how to overload binary operators as friend functions.
  3. Show how to convert from a fundamental type to a user-defined type using a constructor.
  4. Understand exception handling mechanisms using try-catch block statements.

Understand the Application

Complex Numbers

A complex number, c, is an ordered pair of real numbers (doubles). For example, for any two real numbers, s and t, we can form the complex number:

This is only part of what makes a complex number complex. Another important aspect is the definition of special rules for adding, multiplying, dividing, etc. these ordered pairs. Complex numbers are more than simply x-y coordinates because of these operations. Examples of complex numbers in this format are (3, 3), (-1, -5), (1.034, 77.5) and (99.9, -108.5). You will build a class of complex numbers called Complex.

One important property of every complex number, c, is its length, or modulus, defined as follows. If c = (s, t) then:

For example:

The Program Specification

Create a class of Complex numbers.

Private Data

  • double real, double imag - These two doubles define the Complex number and are called the real and imaginary parts. Think of each Complex number as an ordered pair, (real, imag) of doubles.

Public Instance Methods

  • Constructors - Allow Complex objects to be constructed with zero, one or two double arguments. The zero-parameter constructor initializes the complex number to (0, 0). The one-parameter constructor should set the real member to the argument passed and set the imag member to 0. The two-parameter constructor should set both real and imag according to the parameters.  DO ALL THREE VERSIONS IN A SINGLE CONSTRUCTOR USING DEFAULT PARAMETERS.
  • Accessors/Mutators - The usual -- two mutators, two accessors.
  • double modulus() - This will return the double |c|, i.e., the modulus, of the complex number. If the Complex object, c, represents the ordered pair (s, t), then the formula above will give the double value to return.
  • Complex reciprocal() - This is defined in the division operator definition, below.
  • toString() - This will return a string like "(-23.4, 8.9)" to the client.  Do not provide a show() or display() method. You will do this using your insertion operator as shown below.
  • Operators - I will describe several operators that you must implement for the class. Some will be defined externally (which I will call friend operators. However, you may, or may not really need to declare them to be friends - all you need to know is that if I say "friend" I mean implement the operator as a non-member. Otherwise, implement it as a member.
  • Exception Class -

    Division By Zero

    Create your own DivByZeroException as a nested class.

    Make sure that both your reciprocal() and operator/() functions throw this exception (you can do this by only throwing it for reciprocal() if you do it correctly). Test it out in your client with a try/catch block, attempting both a normal, and a fatal division.

    To test for division by zero, look at the reciprocal() and test for that being zero. However, not to test for == 0.0 exactly, because of inaccuracies in computer storage of doubles. Instead, pick a literal like .00000001 and proclaim the a complex object to be zero if its modulus (or modulus squared) is less than that literal value.

Description of the Operators

Operators +, -, * and /

Provide four overloaded operators, +, -, * and /. Implement these operators as friend methods of the class, so that  Complex objects can be combined using these four operations. Also, allow a mixed mode operation containing a double and a Complex (which would return a Complex), by treating a double x, as if it were the complex number (x,0). This should come about naturally as a result of the Complex/Complex operators and the proper constructor definitions, not by creating 3 overloads for each operator.

The rules for adding complex numbers are:

   (r,i) + (s,j) = (r + s, i + j).

Subtraction is defined analogously. Multiplication is defined by the rule:

   (r,i) * (s,j) = (r*s - i*j, r*j + s*i).

To define division, first define the operation reciprocal of the complex number c = (r,i) as follows.  c.reciprocal() should return the complex number = ( r / (r*r + i*i),   -i / (r*r + i*i) ), if (r*r + i*i) is not zero. If (r*r + i*i) is zero, then reciprocal() throws an exception.

Then define division with the help of the reciprocal() function (informally):

   (r,i) / (s,j) = (r,i) * reciprocal(s,j)

Notice that if you correspond a normal double number x, with its complex counterpart, (x,0), then you can think of the ordinary double numbers as a subset of the complex numbers. Also, note that, under this correspondence, these four operations result in ordinary addition, multiplication, etc. for the double subset. Try adding or dividing (6,0) and(3,0) for an example.

Testing Specification

In summary, you should be able to handle the combinations below:

   Complex a(3,-4), b(1.1, 2.1), c;
   double x=2, y= -1.7;

   c = a + b;
   c = x - a;
   c = b * y;

   // and also:
   c = 8 + a;
   c = b / 3.2;

To help you confirm your computations, here are some examples:

(1, 2)  + (3, 4)  = (4, 6) 
(1, 2)  - (3, 4)  = (-2, -2) 
(1, 2)  * (3, 4)  = (-5, 10) 
(1, 2)  / (3, 4)  = (0.44, 0.08) 
(1, 2)  + 10 = (11, 2) 
10 / (3, 4)  = (1.2, -1.6) 

Operators << and =

Overload the insertion and assignment operators in the expected ways.

Operators < and ==

a < b should mean |a| < |b|, that is,  a.modulus() < b.modulus().  a == b should mean (a.real == b.real) && (a.imag == b.imag). Define these two operators to make this so. (Note: < is not standard in math; there is no natural ordering mathematically for complex numbers. However, we will allow it to be defined this way in the problem.)

Pass all Complex parameters as const & and return all values of functions that sensibly return complex numbers (like operator+(), e.g.) as Complex values (not & parameters).

What to Turn In

To avoid Canvas adding a number to your complex files (i.e. same names as lab 5) prepend your initials.  

For example:  Ann Ohlone would be handing in the 3 files: aocomplex.h, aocomplex.cpp, a6.cpp

Hand in 3 files: No zip files.

  • yourinitialscomplex.h : interface file
  • yourinitialscomplex.cpp : implementation file
  • a6.cpp : test driver file

Solutions

Expert Solution

Summary :

Provided implementation for all memeber & friend function along with given test examples.

################ Code #################

#ifndef COMPLEX_H
#define   COMPLEX_H

#include <iostream>
#include <exception>

using namespace std;

class complex
{
        public :
                // constructor with default params 
                complex(double rnum =0, double inum =0);
                double getReal() const;
                double getImag() const;
                void setReal(double rnum);
                void setImag(double inum);
                double modulus() const ;
                complex reciprocal() const throw();
                string toString();
                void operator=( const complex& other );
                bool operator<( const complex& other );
                bool operator==( const complex& other );
                
                complex operator+ ( const double& other );
                complex operator- ( const double& other );
                complex operator* ( const double& other );
                complex operator/ ( const double& other ) throw() ;
                complex operator/ ( const int& other ) throw() ;
                
                complex operator+ ( const complex& other );
                complex operator- ( const complex& other );
                complex operator* ( const complex& other );
                complex operator/ ( const complex& other ) throw() ;
                friend complex operator+(const double& lhs , const complex& rhs );
                friend complex operator-(const double& lhs , const complex& rhs );
                friend complex operator*(const double& lhs , const complex& rhs );
                friend complex operator/(const double& lhs , const complex& rhs ) throw() ;
                
                
                friend complex operator+(const int& lhs , const complex& rhs );
                friend complex operator-(const int& lhs , const complex& rhs );
                friend complex operator*(const int& lhs , const complex& rhs );
                friend complex operator/(const int& lhs , const complex& rhs ) throw() ;
                
                friend ostream & operator<<( ostream &output, const complex &cnum ) ;
                class DivByZeroException : public exception 
                {
                        virtual const char * what() const noexcept
                        {
                                return "Dividing by zero ";
                        }
                } ;
                
        private :
                double real ;
                double imag ;
};


#endif   /* COMPLEX_H */
#include <iostream>
#include "complex.h"
#include <cmath>

using namespace std;

complex::complex(double rnum , double inum )
{
        real = rnum;
        imag = inum;
}

double complex::getReal() const
{
        return real;
}

double complex::getImag() const
{
        return imag;
}

void complex::setReal(double rnum)
{
        real = rnum;
}

void complex::setImag(double inum)
{
        imag = inum;
}

double complex::modulus() const
{
        double result = real*real + imag * imag ;
        return sqrt(abs(result));
        
}

complex complex::reciprocal() const throw() 
{
        // Get the modulus 
        double mod_c = this->modulus();
        mod_c = mod_c * mod_c ;
        if ( mod_c == 0 )
        {
                throw complex::DivByZeroException();
                return complex();
        }
        double r_real = real/mod_c ;
        double r_imag = imag/mod_c;
        
        return complex(r_real,-r_imag);
}

string complex::toString()
{
        char str_buf[100];
        snprintf(str_buf, sizeof(str_buf), "%.2f, %.2f", real,imag);
        string ret_str = str_buf;
        return ret_str;
}

complex complex::operator+( const complex& other )
{
         
         return complex( ( this->getReal() + other.getReal()) , ( this->getImag() + other.getImag()));
}

complex complex::operator-( const complex& other )
{
         
         return complex( (this->getReal() - other.getReal()) , ( this->getImag() -other.getImag()));
}

complex complex::operator*( const complex& other )
{
         double treal = this->getReal() * other.getReal()  - ( this->getImag() * other.getImag() );
         double timg = this->getReal() * other.getImag() + this->getImag() * other.getReal();
         
         return complex( treal, timg );
}


complex complex::operator/( const complex& other ) throw()
{
        complex tmp = other.reciprocal();
        
        return *this * tmp ;
}


complex complex::operator+ ( const double& other )
{
        return complex( other + this->getReal(), this->getImag());
}

complex complex::operator- ( const double& other )
{
        return complex( this->getReal() - other, this->getImag());
}
complex complex::operator* ( const double& other )
{
        return complex( other * this->getReal(), other * this->getImag());
}

complex complex::operator/ ( const double& other ) throw()
{
        if ( other == 0 ) 
        {
                throw complex::DivByZeroException() ;
                return complex();
        } else 
                return complex(  this->getReal() / other , this->getImag()/ other);
}


complex complex::operator/ ( const int& other ) throw() 
{
        if ( other == 0 ) 
        {
                throw complex::DivByZeroException() ;
                return complex();
        }
        
        return complex(  this->getReal() / other , this->getImag()/ other);
}


void complex::operator = (const complex &other ) { 
          this->real = other.getReal();
         this->imag = other.getImag();
      }
      
bool complex::operator < ( const complex & rhs )
{
        double lval = this->modulus();
        double rval = rhs.modulus();
        return (lval < rval );
}

bool complex::operator == ( const complex & rhs )
{
        double lval = this->modulus();
        double rval = rhs.modulus();
        return (( lval == rval ) && ( this->getReal() == rhs.getReal()) && ( this->getImag() == rhs.getImag()) );
}

ostream & operator<<( ostream &output, const complex &cnum ) { 
         output << "(" << cnum.getReal()  << ", " << cnum.getImag() << ")";
         return output;            
      }
          
          
complex operator+(const double& lhs , const complex& rhs )
{
        return complex( lhs + rhs.getReal() , rhs.getImag());
}

complex operator-(const double& lhs , const complex& rhs )
{
        return complex( lhs - rhs.getReal() , rhs.getImag());
}

complex operator*(const double& lhs , const complex& rhs )
{
        return complex( lhs * rhs.getReal() , lhs * rhs.getImag());
}

complex operator/(const double& lhs , const complex& rhs ) throw()
{
        complex tmp = rhs.reciprocal();
        return complex( lhs* tmp.getReal() , lhs*tmp.getImag());
}

          
complex operator+(const int& lhs , const complex& rhs )
{
        return complex( lhs + rhs.getReal() , rhs.getImag());
}

complex operator-(const int& lhs , const complex& rhs )
{
        return complex( lhs - rhs.getReal() , rhs.getImag());
}

complex operator*(const int& lhs , const complex& rhs )
{
        return complex( lhs * rhs.getReal() , lhs * rhs.getImag());
}

complex operator/(const int& lhs , const complex& rhs ) throw()
{
        complex tmp = rhs.reciprocal();
        return complex( lhs* tmp.getReal() , lhs*tmp.getImag());
}
#include <iostream>
#include "complex.h"

int main()
{
        complex a(3,-4), b(1.1, 2.1), c ;
        double x =2 , y = -1.7;
        
        c = a+ b ;
        c = x - a ;
        c = b* y;
        
        cout << a ;
        
        cout << "  a : " << a  << "\n"
                <<  " b : " << b << "\n"
                << " c : " << c << "\n";
        c = 8 + a ;
        cout <<  " c = 8 + a -> " << c << "\n";
        
        c = b / 3.2 ;
        cout <<  " c = b/3.2  -> " << c << "\n";
        
        complex x1(1,2), x2(3,4) ;
        
        cout << x1 << " + " << x2 << " = " <<  x1 + x2 <<  "\n";
        cout << x1 << " + " << x2 << " = " <<  x1 - x2 <<  "\n";
        cout << x1 << " + " << x2 << " = " <<  x1 * x2 <<  "\n";
        cout << x1 << " + " << x2 << " = " <<  x1 / x2 <<  "\n";
        cout << x1 << " + " << x2 << " = " <<  x1 + 10 <<  "\n";
        cout << x1 << " + " << x2 << " = " <<  10/ x2 <<  "\n";
        

}

################## Output ###################


Related Solutions

Lab Assignment Objectives 'Be able to overload combined binary operators as member operator functions. Show how...
Lab Assignment Objectives 'Be able to overload combined binary operators as member operator functions. Show how to overload binary operators as friend functions. Show how to convert from a fundamental type to a user-defined type using a constructor. Understand exception handling mechanisms using try-catch block statements. Understand the Application Complex Numbers A complex number, c, is an ordered pair of real numbers (doubles). For example, for any two real numbers, s and t, we can form the complex number: This...
C++ Programming 19.2 Operator Overloading practice Write the prototypes and functions to overload the given operators...
C++ Programming 19.2 Operator Overloading practice Write the prototypes and functions to overload the given operators in the code main.cpp //This program shows how to use the class rectangleType. #include <iostream> #include "rectangleType.h" using namespace std; int main() { rectangleType rectangle1(23, 45); //Line 1 rectangleType rectangle2(12, 10); //Line 2 rectangleType rectangle3; //Line 3 rectangleType rectangle4; //Line 4 cout << "Line 5: rectangle1: "; //Line 5 rectangle1.print(); //Line 6 cout << endl; //Line 7 cout << "Line 8: rectangle2: "; //Line...
This chapter uses the class rectangleType to illustrate how to overload the operators +, *, ==,...
This chapter uses the class rectangleType to illustrate how to overload the operators +, *, ==, !=, >>, and <<. In this exercise, first redefine the class rectangleType by declaring the instance variables as protected and then overload additional operators as defined in parts a to c. 1.Overload the pre- and post-increment and decrement operators to increment and decrement, respectively, the length and width of a rectangle by one unit. (Note that after decrementing the length and width, they must...
Show that Hermitian operators have real eigenvalues. Show that eigenvectors of a Hermitian operator with unique...
Show that Hermitian operators have real eigenvalues. Show that eigenvectors of a Hermitian operator with unique eigenvalues are orthogonal. Use Dirac notation for this problem.
Overloading the insertion (<<) and extraction (>>) operators for class use requires creating operator functions that...
Overloading the insertion (<<) and extraction (>>) operators for class use requires creating operator functions that use these symbols but have a parameter list that includes a class ____. object address reference data type Flag this Question Question 210 pts When overloading the insertion operator to process a Complex object, it’s important to understand that you’re overloading an operator in the ____ class. istream operator Complex ostream Flag this Question Question 310 pts ____ class variables are allocated memory locations...
Lab Objectives Be able to declare a new class Be able to write a constructor Be...
Lab Objectives Be able to declare a new class Be able to write a constructor Be able to write instance methods that return a value Be able to write instance methods that take arguments Be able to instantiate an object Be able to use calls to instance methods to access and change the state of an object Introduction Everyone is familiar with a television. It is the object we are going to create in this lab. First we need a...
In class we discussed how to overload the + operator to enable objects of type Fraction to be added together using the + operator.
2.(a) Fraction Operators Objective:In class we discussed how to overload the + operator to enable objects of type Fraction to be added together using the + operator. Extend the Fraction class definition so that the -, * and / operators are supported. Write a main function that demonstrates usage of all of these operators.(b)More Custom Types Objective:Define a set of classes that represent a Schedule and Course in the context of a university student who has a schedule with a...
6.28 LAB: Convert to binary - functions Write a program that takes in a positive integer...
6.28 LAB: Convert to binary - functions Write a program that takes in a positive integer as input, and outputs a string of 1's and 0's representing the integer in binary. For an integer x, the algorithm is: As long as x is greater than 0 Output x % 2 (remainder is either 0 or 1) x = x / 2 Note: The above algorithm outputs the 0's and 1's in reverse order. You will need to write a second...
Wondering where to start on this C++ homework assignment involving friend functions and overloading operators implemented...
Wondering where to start on this C++ homework assignment involving friend functions and overloading operators implemented in a Rational class. These are the instructions: Your class will need to store two internal, integer values for each Rational number, the numerator (top) and denominator (bottom) of the fraction. It will have three constructor functions, with zero, one and two arguments, used as follows:     Rational test1, test2(10), test3(1, 2); The declaration for test1 calls the default (no argument) constructor, which should...
4.3 Lab: Queues 1 Write the c++ implementation of the following four member functions of the...
4.3 Lab: Queues 1 Write the c++ implementation of the following four member functions of the Queue class: getLength(): returns the number of elements in the queue isEmpty(): returns true if the queue is empty, false otherwise peek(): returns the value at the front of the queue without removing it. Assumes queue is not empty (no need to check) peekRear(): returns the value at the end of the queue without removing it. Assumes queue is not empty (no need to...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT