Task 1: Complex Numbers
Task
Create your own data type for complex numbers that can be used as a
drop-in replacement for double. The definition of the data type and the
forward declarations of operators must be in file complex.h
, while the
implementation of operators must be in file complex.cpp
.
- Define a struct named
Complex
that represents a complex number in the cartesian form. As data type use floating point numbers withdouble
precision. - Implement input and output
(>>, <<)
operators for reading and writing of complex numbers.
A complex number \((x pm yi)\) is represented in the format [x,y]
,
where x
and y
follows the format of floating point numbers with
double
precision.
E.g., [-2,5]
represents \((-2 + 5i)\) . Important: No spaces.
Note: You can assume that your input value is a well-formatted complex number.
- Implement arithmetic operators for addition, subtraction, multiplication, and division \((+,-,*,/)\) of complex numbers. For the division, you may assume that the squared modulus of the divisor is not zero, even after rounding it to a floating point number. Finally, you do not need to treat the case of division by zero.
- Implement the negation operator \((-)\) of complex numbers.
- Implement comparison operators for equality and inequality \((==,!=)\) of complex numbers.
Hint: recall from Exercise 5 how to correctly compare floating point numbers.
Solution
complex.h
#pragma once
#include <cmath>
#include <iostream>
struct Complex {
double a;
double b;
};
// arithmetic operators
Complex operator+(const Complex &cn1, const Complex &cn2);
Complex operator-(const Complex &cn1, const Complex &cn2);
Complex operator*(const Complex &cn1, const Complex &cn2);
Complex operator/(const Complex &cn1, const Complex &cn2);
// negation operator
Complex operator-(const Complex &cn1);
// equality and inequality operators
bool operator==(const Complex &cn1, const Complex &cn2);
bool operator!=(const Complex &cn1, const Complex &cn2);
// reads a complex number from input
std::istream &operator>>(std::istream &in, Complex &a);
std::ostream &operator<<(std::ostream &out, const Complex &a);
complex.cpp
#include "complex.h"
#include <cstdlib>
std::istream &operator>>(std::istream &in, Complex &a) {
char open;
char comma;
char close;
double aa;
double ab;
in >> open;
if (open == '[') {
in >> aa >> comma >> ab >> close;
if (comma == ',' && close == ']') {
a.a = aa;
a.b = ab;
} else {
std::cerr << "Invalid Input!";
}
} else {
std::cerr << "Invalid Input!";
}
return in;
}
std::ostream &operator<<(std::ostream &out, const Complex &a) {
return out << "[" << a.a << "," << a.b << "]";
}
Complex operator+(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = cn1.a + cn2.a;
double b = cn1.b + cn2.b;
res.a = a;
res.b = b;
return res;
}
Complex operator-(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = cn1.a - cn2.a;
double b = cn1.b - cn2.b;
res.a = a;
res.b = b;
return res;
}
Complex operator*(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = (cn1.a * cn2.a) - (cn1.b * cn2.b);
double b = (cn1.a * cn2.b) + (cn1.b * cn2.a);
res.a = a;
res.b = b;
return res;
}
Complex operator/(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = (cn1.a * cn2.a + cn1.b * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
double b = (cn1.b * cn2.a - cn1.a * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
res.a = a;
res.b = b;
return res;
}
Complex operator-(const Complex &cn1) {
Complex res;
double a = -cn1.a;
double b = -cn1.b;
res.a = a;
res.b = b;
return res;
}
bool operator==(const Complex &cn1, const Complex &cn2) {
double epsilon = 0.1;
return (std::abs(cn1.a - cn2.a) < epsilon) &&
(std::abs(cn1.b - cn2.b) < epsilon);
}
bool operator!=(const Complex &cn1, const Complex &cn2) {
double epsilon = 0.1;
return (std::abs(cn1.a - cn2.a) > epsilon) ||
(std::abs(cn1.b - cn2.b) > epsilon);
}
Made by JirR02 in Switzerland 🇨🇭