C++ Class for Complex Numbers with Demo Application

Today, we will see a real and simple C++ class for complex numbers. We will implement: 1) Addition (+) 2) Subtraction (-) 3) Multiplication (*) 4) Division (/) The class header, called MyComplexNumber.h will be declared like this:
  1. #ifndef MYCOMPLEXNUMBER_H
  2. #define MYCOMPLEXNUMBER_H
  3.  
  4. #include <string>
  5.  
  6. using namespace std;
  7.  
  8. class MyComplexNumber {
  9. double real;
  10. double imaginary;
  11.  
  12. MyComplexNumber operator=(const MyComplexNumber&);
  13. friend MyComplexNumber operator+(const MyComplexNumber&, const MyComplexNumber&);
  14. friend MyComplexNumber operator-(const MyComplexNumber&, const MyComplexNumber&);
  15. friend MyComplexNumber operator*(const MyComplexNumber&, const MyComplexNumber&);
  16. friend MyComplexNumber operator/(const MyComplexNumber&, const MyComplexNumber&);
  17.  
  18. public:
  19. MyComplexNumber();
  20. MyComplexNumber(double, double);
  21. MyComplexNumber(const MyComplexNumber&);
  22.  
  23. double getReal() const;
  24. double getImaginary() const;
  25. string toString() const;
  26. };
  27.  
  28. #endif /* MYCOMPLEXNUMBER_H */
The only public members are: - the constructors - get functions (to read real/imaginary part) - toString function for beautiful output Now, the next step is understanding how this all works. First, we have created a helper function to convert double to string - you can use this in other projects too!
  1. string DoubleToString(double val) {
  2. stringstream ss;
  3. ss << val;
  4. return ss.str();
  5. }
It is obvious how we have used a stringstream to make it quick, and simple. Also, this doesn't leave junk in the memory. Next thing, we need to understand how overloading the operators works. The operator= is different in the code, and is like this:
  1. MyComplexNumber MyComplexNumber::operator=(const MyComplexNumber& rhs) {
  2. MyComplexNumber res(rhs.getReal(), rhs.getImaginary());
  3. return res;
  4. }
It is a simple one - only uses the 2nd constructor to return the left-hand side. The other operators are declared differently. The rules used for computation are the mathematical formulas, so there is nothing about C++ techniques, just about mathematics.
  1. MyComplexNumber operator+(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  2. MyComplexNumber add(lhs);
  3. add.real += rhs.real;
  4. add.imaginary += rhs.imaginary;
  5. return add;
  6. }
  7.  
  8. MyComplexNumber operator-(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  9. MyComplexNumber minus(lhs);
  10. minus.real -= rhs.real;
  11. minus.imaginary -= rhs.imaginary;
  12. return minus;
  13. }
  14.  
  15. MyComplexNumber operator*(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  16. MyComplexNumber multiply(lhs);
  17. multiply.real = lhs.real * rhs.real - lhs.imaginary * rhs.imaginary;
  18. multiply.imaginary = lhs.real * rhs.imaginary + lhs.imaginary * rhs.real;
  19. return multiply;
  20. }
  21.  
  22. MyComplexNumber operator/(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  23. MyComplexNumber divide(lhs);
  24. double squareSum = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary;
  25. divide.real = (lhs.real * rhs.real + lhs.imaginary * rhs.imaginary) / squareSum;
  26. divide.imaginary = (lhs.imaginary * rhs.real - lhs.real * rhs.imaginary) / squareSum;
  27. return divide;
  28. }
As you can see, we have used the copy constructor in each case for simplicity. Then, being friend functions, we can access private members (real, imaginary). For * and /, we could've used this:
  1. MyComplexNumber x;
The full listing for MyComplexNumber.cpp is here:
  1. #include <string>
  2. #include <sstream>
  3. #include "MyComplexNumber.h"
  4.  
  5. using namespace std;
  6.  
  7. string DoubleToString(double val) {
  8. stringstream ss;
  9. ss << val;
  10. return ss.str();
  11. }
  12.  
  13. MyComplexNumber::MyComplexNumber() {
  14. real = 0;
  15. imaginary = 0;
  16. }
  17.  
  18. MyComplexNumber::MyComplexNumber(double r, double i) {
  19. real = r;
  20. imaginary = i;
  21. }
  22.  
  23. MyComplexNumber::MyComplexNumber(const MyComplexNumber &other) {
  24. real = other.getReal();
  25. imaginary = other.getImaginary();
  26. }
  27.  
  28. string MyComplexNumber::toString() const {
  29. string s = "";
  30. s += DoubleToString(real);
  31. s += " ";
  32. if (imaginary > 0) {
  33. s += "+ " + DoubleToString(imaginary) + "i";
  34. } else if (imaginary < 0) {
  35. s += "- " + DoubleToString(-imaginary) + "i";
  36. }
  37. return s;
  38. }
  39.  
  40. double MyComplexNumber::getReal() const {
  41. return real;
  42. }
  43.  
  44. double MyComplexNumber::getImaginary() const {
  45. return imaginary;
  46. }
  47.  
  48. MyComplexNumber operator+(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  49. MyComplexNumber add(lhs);
  50. add.real += rhs.real;
  51. add.imaginary += rhs.imaginary;
  52. return add;
  53. }
  54.  
  55. MyComplexNumber operator-(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  56. MyComplexNumber minus(lhs);
  57. minus.real -= rhs.real;
  58. minus.imaginary -= rhs.imaginary;
  59. return minus;
  60. }
  61.  
  62. MyComplexNumber operator*(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  63. MyComplexNumber multiply(lhs);
  64. multiply.real = lhs.real * rhs.real - lhs.imaginary * rhs.imaginary;
  65. multiply.imaginary = lhs.real * rhs.imaginary + lhs.imaginary * rhs.real;
  66. return multiply;
  67. }
  68.  
  69. MyComplexNumber operator/(const MyComplexNumber& lhs, const MyComplexNumber& rhs) {
  70. MyComplexNumber divide(lhs);
  71. double squareSum = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary;
  72. divide.real = (lhs.real * rhs.real + lhs.imaginary * rhs.imaginary) / squareSum;
  73. divide.imaginary = (lhs.imaginary * rhs.real - lhs.real * rhs.imaginary) / squareSum;
  74. return divide;
  75. }
  76.  
  77. MyComplexNumber MyComplexNumber::operator=(const MyComplexNumber& rhs) {
  78. MyComplexNumber res(rhs.getReal(), rhs.getImaginary());
  79. return res;
  80. }
Then, we created a small demo program to demonstrate how accurately and perfectly this program outputs results! You can change the toString() function, if you want to use lass digits after the '.'. Here is the main.cpp source code listing:
  1. #include <iostream>
  2. #include "MyComplexNumber.h"
  3.  
  4. using namespace std;
  5.  
  6. int main(int argc, char** argv) {
  7. MyComplexNumber a(2, 3), b(4, -5);
  8. cout << a.toString() << endl;
  9. cout << b.toString() << endl;
  10.  
  11. //Test +
  12. MyComplexNumber c = a + b;
  13. cout << "(" << a.toString() << ") + ";
  14. cout << "(" << b.toString() << ") = ";
  15. cout << c.toString() << endl;
  16.  
  17. //Test -
  18. MyComplexNumber d = a - b;
  19. cout << "(" << a.toString() << ") - ";
  20. cout << "(" << b.toString() << ") = ";
  21. cout << d.toString() << endl;
  22.  
  23. //Test *
  24. MyComplexNumber e = a * b;
  25. cout << "(" << a.toString() << ") * ";
  26. cout << "(" << b.toString() << ") = ";
  27. cout << e.toString() << endl;
  28.  
  29. //Test /
  30. MyComplexNumber f = a / b;
  31. cout << "(" << a.toString() << ") / ";
  32. cout << "(" << b.toString() << ") = ";
  33. cout << f.toString() << endl;
  34.  
  35. return 0;
  36. }
From the above example, the output will show:
  1. 2 + 3i
  2. 4 - 5i
  3. (2 + 3i) + (4 - 5i) = 6 - 2i
  4. (2 + 3i) - (4 - 5i) = -2 + 8i
  5. (2 + 3i) * (4 - 5i) = 23 + 2i
  6. (2 + 3i) / (4 - 5i) = -0.170732 + 0.536585i
Have fun with operator overloading and solving complex number problems faster!

Tags

Add new comment