In: Computer Science
Lab Assignment Objectives
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
Public Instance Methods
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.
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 ###################