In a previous article, we talked about complex numbers in Python using built-in classes and attributes to perform operations on them. But, imagine if Python didn't come equipped with these conveniences. How would we go about implementing complex operations? We can explore that concept by utilizing built-in mathematical operations to create our own complex class in Python.
To start off, we need to initialize our complex number:
def __init__ (self, real, imag=0.0): '''Form complex number''' self.real = real self.imag = imag
As we've stated previously, complex numbers are created from a real and an imaginary number. The
__init__ operator defines the values that form the complex number by initializing the value of
You may have noticed that
imag (short for imaginary) has been set equal to zero. This is because zero is a purely imaginary number. Therefore, if a user does not pass any value into
imag, then this ensures that it will still be imaginary.
We have a class that defines complex numbers by their real and imaginary parts, now we're ready to begin creating operations to perform on complex numbers.
When you add complex numbers together, you are only able to combine like terms. In other words, we must add together the real and imaginary components of both numbers as separate pieces. Taking a look at the addition class below, we can see that we have defined the first number as
self and the second as
After initializing our two complex numbers, we can then add them together as seen below the addition class.
def __add__(self, other): return Complex(self.real + other.real, self.imag + other.imag) i = complex(2, 10j) k = complex(3, 5j) add = i + k print(add) # Output: (5+15j)
Subtraction works very similarly to addition with complex numbers. Once again, we can only combine like terms, therefore, it's important that we keep these separate when performing the subtraction operation.
Using the same variables from the previous example,
k, let's see the result of the subtraction of these two complex numbers.
def __sub__(self, other): return Complex(self.real - other.real, self.imag - other.image) subtract = i - k # Output: (-1+5j)
As expected, when you subtract 3 from 2 the result is -1, and 10j - 5j resulted in 5j.
Multiplication is a bit trickier. Unlike addition and subtraction, we will now have to combine coefficients of the imaginary numbers with the real numbers. However, the result must be returned as a complex number in the end.
Before we jump into the code, let's take a look at how the math works out under the hood. As you can see below, we break the problem up into two separate pieces: one that solves for the real number and one that solves for the imaginary. This should look familiar to anyone who knows algebra.
# The problem written out (2 + 10j) * (3 + 5j) # Solving for the real number (2 * 3) - (10j * 5j) 6 + 50 -------------------- 56 # Once we multiply 10j by 5j, j becomes j^2. # Which is also equal to -1, causing - to change to + # Solving for the imaginary number (10j * 3) + (2 * 5j) 30j + 10j -------------------- 40j /* We are combining the coefficients from the reals with the imaginary numbers */ # Final result: 56 + 40j
The real part of the complex number is solved by subtracting
(2 * 3) - (10j * 5j) but this becomes addition because an imaginary number is equivalent to -1. In other words, the real number part of the equation can be seen as:
(2 * 3) + (10 * 5).
Understanding the math involved in solving for the multiplication of two complex numbers is an important first step. We are ready to move forward with the class. As we look below, you'll notice that the math we performed above is laid out very similarly to the code itself.
def __mul__(self, other): return Complex(self.real * other.real - self.imag * other.imag, self.imag * other.real + self.real * other.real) multiply = i * k # Output:
Like multiplication, dividing complex numbers can become messy pretty quickly. Especially if you're not familiar with the fundamental concepts of how to solve for the quotient of two complex numbers.
Continuing with the same complex numbers used throughout this article, we begin with the problem that solves for the real number. Similar to multiplication, division of complex numbers can be broken down into two separate equations for each part of the complex number.
Then we move onto the second half of the problem in which we solve for the imaginary part. This is pretty straight forward as we're just following the same basic division principles that we use with real numbers.
Once we have two pieces for each - the real and imaginary parts of the complex number - then we need to combine them in order to get a final result.
# Divisor (3**2 + 5j**2) (9 - 25) # Solving real number (2*3 - 10j*5j) / (9 - 25) (6 + 50) / (-16) (-44 / -16) -------------------------- -3.5 # Solving imaginary number (10j*3 + 2*5j) / (9 - 25) (30j + 10j) / (-16) 40j / (-16) -------------------------- -2.5j # Final result: (-3.5-2.5j)
The divisor in the problem above is found by raising the real and imaginary parts of the
other value to the second power. Since we are dividing by
k those are 3 and 5j.
The j of 5j is eliminated once the number is raised to the second power, turning it into a real number and allowing it to be combined with
Let's see this written out in Python:
def __truediv__(self, other): divisor = (other.real**2 + other.imag**2) return Complex((self.real * other.real) - (self.imag * other.imag)/divisor, (self.imag * other.real) + (self.real * other.imag)/divisor) divide = i / k # Output: (-3.5-2.5j)
You may have noticed that the division operator is named
__truediv__ rather than
div. This is due to the fact that
__truediv__ is a built-in operation in Python 3 that is able to recognize the division operator
i / k would be considered illegal and would result in an error message.
On a less math-heavy note, let's try to find the absolute value of a complex number. To do so, we must extract the coefficient from the imaginary part and combine that with the real number. We've already done this with the divisor in the last example.
# We are solving for the absolute value of i = (2+10j) (2**2 + (10j**2)*(-1)) 4 + (-100)*(-1) 4 + 100 ---------------------- 104 sqrt(104) # Final result: 10.198039027185569
As we can see with i
(2+10j), we are raising the real and imaginary numbers to the second power. After we have turned 10j into -100, we must multiply by -1 because we have eliminated
j and made the coefficient into a negative number. However, the result will be inaccurate if we subtract 100 from 4 because we cannot solve for the square root of a negative.
import math from math import sqrt def __abs__(self): new = (self.real**2 + (self.imag**2)*-1) return Complex(sqrt(new.real)) abs(i) # Output: 10.198039027185569 abs(k) # Output: 5.830951894845301
You may be wondering why it is even necessary to raise the numbers to the second power if we're just going to solve for the square root, anyway.
As noted earlier, raising the real and imaginary numbers to the second power pulls them out of the complex number by eliminating all imaginary parts (j squared is -1). This allows us to combine the two numbers in order to find their absolute value.
So far we've discussed addition, subtraction, multiplication, division, and absolute value with complex numbers. You can contribute even more operations to your complex class on your own. But, first, let's clean up the code and see how it works all together.
import math from math import sqrt class Complex(object): def __init__(self, real, imag=0.0): self.real = real self.imag = imag # Formats our results print(self.real + self.imag) def __add__(self, other): print('\nSum:') return Complex(self.real + other.real, self.imag + other.imag) def __sub__(self, other): print('\nDifference:') return Complex(self.real - other.real, self.imag - other.imag) def __mul__(self, other): print('\nProduct:') return Complex((self.real * other.real) - (self.imag * other.imag), (self.imag * other.real) + (self.real * other.imag)) def __truediv__(self, other): print('\nQuotient:') r = (other.real**2 + other.imag**2) return Complex((self.real*other.real - self.imag*other.imag)/r, (self.imag*other.real + self.real*other.imag)/r) def __abs__(self): print('\nAbsolute Value:') new = (self.real**2 + (self.imag**2)*-1) return Complex(sqrt(new.real)) i = Complex(2, 10j) k = Complex(3, 5j) # Add i + k # Subtract i - k # Multiply i * k # Divide i / k # Absolute value abs(i) abs(k) # Output: (2+10j) (3+5j) Sum: (5+15j) Difference: (-1+5j) Product: (56+40j) Quotient: (-3.5-2.5j) Absolute Value: 10.198039027185569 Absolute Value: 5.830951894845301
As you see from our resulting output, we can add a new line (
\n) and label the operation so that our answers are returned in a neater and more readable format for the user. There is much more to expand upon this complex class, explore these concepts on your own to create a deeper understanding of Python and its operators.
With this article at OpenGenus, you must have the complete idea of implementing and designing Complex Numbers using classes in Python. Enjoy.