What are complex values in python?
Most general-purpose programming languages have either no support or limited support for complex numbers. Your typical options are learning some specialized tool like MATLAB or finding a third-party library. Python is a rare exception because it comes with complex numbers built in. Show
Despite the name, complex numbers aren’t complicated! They’re convenient in tackling practical problems that you’ll get a taste of in this tutorial. You’ll explore vector graphics and sound frequency analysis, but complex numbers can also help in drawing fractals, such as the Mandelbrot set. In this tutorial, you’ll learn how to:
If you need a quick refresher or a gentle introduction to the theory of complex numbers, then you can watch Khan Academy’s video series. To download the sample code used throughout this tutorial, click the link below: Creating Complex Numbers in PythonCreating and manipulating complex numbers in Python isn’t much different from other built-in data types, particularly numeric types. It’s possible because the language treats them as first-class citizens. This means you can express mathematical formulas that involve complex numbers with little overhead. Python lets you use complex numbers in arithmetic expressions and call functions on them just like you would with other numbers in Python. It leads to elegant syntax that reads almost like a math textbook. Complex Number LiteralThe quickest way to define a complex number in Python is by typing its literal directly in the source code: Although this looks like an algebraic formula, the expression to the right of the equals sign is already a fixed value that needs no further evaluation. When you check its type, you’ll confirm that it’s indeed a complex number: >>>
How is that different from adding two numbers with the plus operator? A clear giveaway is the letter >>>
By the way, you can use floating-point numbers to create complex numbers, too: >>>
Complex number literals in Python mimic the mathematical notation, which is
also known as the standard form, the algebraic form, or sometimes the canonical form, of a complex number. In Python, you can use either lowercase If you learned about complex numbers in math class, you might have seen them expressed using an The traditional notation for complex numbers uses the letter
This was brought up on Python’s bug tracker over a decade ago, and Python’s creator, Guido van Rossum himself, closed the issue with this comment:
So there
you have it. Unless you want to start using MATLAB, you’ll have to live with using The algebraic form of a complex number follows the standard rules of algebra, which is convenient in performing arithmetic. For example, addition has a commutative property, which lets you swap the order of the two parts of a complex number literal without changing its value: >>>
Similarly, you can substitute addition for subtraction in a complex number literal because the minus sign is just a shorthand notation for an equivalent form: >>>
Does a complex number literal in Python always have to comprise two numbers? Can it have more? Are they ordered? To answer these questions, let’s run some
experiments. Unsurprisingly, if you specify only one number, without the letter >>>
On the other hand, appending the letter >>>
Strictly speaking, from a mathematical standpoint, you’ve just created a pure imaginary number, but Python can’t represent it as a stand-alone data type. Therefore, without the other part, it’s just a complex number . How about the opposite? To create a complex number without the imaginary part, you can take advantage of zero and add or subtract it like so: >>>
In fact, both parts of the complex number are always there. When you don’t see one, it means that it has a value of zero. Let’s check what happens when you try stuffing more terms into the sum than before: >>>
This time, your expression is no longer a literal because Python evaluated it into a complex number comprising only two parts. Remember that the basic rules of algebra carry over to complex numbers, so if you group similar terms and
apply component-wise addition, then you’ll end up with Notice how Python displays complex numbers by default. Their textual representation contains an enclosing pair of parentheses, a lowercase letter Complex numbers that also happen to be pure imaginary numbers show up without parentheses and only reveal their imaginary part: >>>
This helps differentiate imaginary numbers from most complex numbers made up of real and imaginary parts. complex() Factory FunctionPython has a built-in function, In this form, it resembles a tuple or an ordered pair of ordinary numbers. The analogy isn’t that far-fetched. Complex numbers have a geometric interpretation in the Cartesian coordinate system that you’ll explore in a bit. You can think of complex numbers as two-dimensional. The complex number factory function accepts two numeric
parameters. The first one represents the real part, while the second one represents the imaginary part denoted with the letter >>>
Both parameters are optional, with default values of zero, which makes it less clunky to define complex numbers without the imaginary part or both the real and imaginary parts: >>>
The single-argument version can be useful in type casting. For example, you can pass a nonnumeric value like a string literal to obtain a corresponding >>>
Later, you’ll
find out how to make your classes compatible with this type casting mechanism. Interestingly, when you pass a complex number to >>>
That’s consistent with how other types of numbers in Python work because they’re all immutable. To make a distinct copy of a complex number, you must call the function with both arguments again or declare another variable with the complex number literal: >>>
When you provide two arguments to the function, they must always be numbers, such as >>>
Things get seemingly more bizarre when you supply the >>>
However, when two arguments are present and at least one of them is a complex number, you’ll get results that may be difficult to explain at first sight: >>>
To get the answers, let’s take a peek at the factory function’s docstring or the online documentation, which explain what’s going on under the hood when you call
In this explanation, When would you want to use the Getting to Know Python Complex NumbersIn mathematics, complex numbers are a superset of real numbers, which means that every real number is also a complex number whose imaginary part is equal to zero. Python models this relationship through a concept called the numeric tower, described in PEP 3141: >>>
The built-in >>>
The floating-point value >>>
The difference between Abstract base classes, which are denoted in red on the diagram above, can bypass the regular inheritance check mechanism by registering unrelated classes as their virtual
subclasses. That’s why a floating-point value in the example appears to be an instance of Accessing Real and Imaginary PartsTo get the real and imaginary parts of a complex number in Python, you can reach for the corresponding >>>
Both properties are read-only because complex numbers are immutable, so trying to assign a new value to either of them will fail: >>>
Since every number in Python is a more specific type of a complex number, attributes and methods defined in >>>
The imaginary part of such numbers is always zero. Calculating the Conjugate of a Complex NumberPython complex numbers have only three public members. Apart from
the >>>
For numbers whose imaginary part equals zero, it won’t have any effect: >>>
This operation is its own inverse, so calling it twice will get you the original number you started with: >>>
While it may seem of little value, the complex conjugate has a few useful arithmetic properties that can help calculate the division of two complex numbers with pen and paper, among many other things. Complex Numbers ArithmeticSince For now, remembering a single rule will let you apply your primary school knowledge of arithmetic to calculate basic operations involving complex numbers. The rule to remember is the definition of the imaginary unit, which satisfies the following equation: It doesn’t look right when you think of AdditionThe sum of two or more complex numbers is equivalent to adding their real and imaginary parts component-wise: >>>
Earlier, you found out that algebraic expressions composed of real and imaginary numbers follow the standard rules of algebra. When you write it down algebraically, you’ll be able to apply the distributive property and simplify the formula by factoring out and grouping common terms: Python automatically promotes operands to the >>>
That is similar to the implicit conversion from SubtractionSubtracting complex numbers is analogous to adding them, which means you can also apply it element-wise: >>>
Unlike the sum, however, the order of operands is significant and yields different results just like with real numbers: >>>
You can also use the unary minus operator (-) to make the negative of a complex number: >>>
This inverts both the real and the imaginary parts of the complex number. MultiplicationThe product of two or more complex numbers gets more interesting: >>>
How on Earth did you end up with a negative number out of only positive ones? To answer this question, you have to recall the definition of the imaginary unit and rewrite the expression in terms of real and imaginary parts: The key observation to make is that DivisionDividing complex numbers can look intimidating at first encounter: >>>
Believe it or not, you’re able to get the same result using nothing more than a pen and paper! (Okay, a calculator might save you some headaches down the line.) When both numbers are expressed in their standard forms, the trick is to multiply the numerator and the denominator by the conjugate of the latter: The denominator becomes a squared modulus of the divisor. You’ll learn more about the modulus of complex numbers later. When you continue deriving the formula, this is what you’ll get: Note that complex numbers don’t support floor division, also known as integer division: >>>
This used to work in Python 2.x but was later removed to avoid ambiguity. ExponentiationYou can raise complex numbers to a power using the binary exponentiation operator ( >>>
Both the base and the exponent can be of any numeric types, including integer, floating-point, imaginary, or complex: >>>
Manual exponentiation of complex numbers becomes very difficult when they’re expressed in their standard form. It’s much more convenient to rewrite the number in the trigonometric form and calculate the power using some basic trigonometry. If you’re interested in the math involved, check out De Moivre’s formula, which lets you do that. Using Python Complex Numbers as 2D VectorsYou can visualize complex numbers as points or vectors on a Euclidean plane in the Cartesian or rectangular coordinate system: The X-axis on the complex plane, also known as the Gauss plane or Argand diagram, represents the real part of a complex number, while the Y-axis represents its imaginary part. This fact leads to one of the coolest features of the Getting the CoordinatesThe Bermuda Triangle is a legendary region known for its paranormal phenomena that spans across the southern tip of Florida, Puerto Rico, and the tiny island of Bermuda. Its vertices are approximately designated by the three major cities whose geographical coordinates are the following:
After converting these coordinates to decimal degrees, you’ll end up with two floating-point numbers for each city. You can use the
Negative longitude values represent the western hemisphere, while positive latitude values represent the northern hemisphere. Bear in mind that these are spherical coordinates. To correctly project them onto a flat plane, you’d need to account for the curvature of Earth. One of the first map projections used in cartography was the Mercator projection, which helped sailors navigate their ships. But let’s ignore all that and assume that values are already expressed in the rectangular coordinate system. When you plot the numbers on a complex plane, you’ll get a rough depiction of the Bermuda Triangle: In the companion materials, you’ll find an interactive Jupyter Notebook that plots the Bermuda Triangle using the Matplotlib library. To download the source code and materials for this tutorial, click the link below: If you don’t like calling the
If you needed to pack more attributes on a city, you could use a named tuple or a data class or create a custom class. Calculating the MagnitudeThe magnitude, also known as the modulus or radius of a complex number, is the length of the vector that depicts it on a complex plane: You can calculate it from the Pythagorean theorem by taking the square root of the sum of the squared real part and the squared imaginary part: You would think that Python would let you calculate the length of such a vector with the built-in >>>
This function removes the sign from integers that you pass in, but for complex numbers, it returns the magnitude or vector length: >>>
You might remember from an earlier section that a complex number multiplied by its conjugate produces its magnitude squared. Finding the Distance Between Two PointsLet’s find the Bermuda Triangle’s geometric center and the distances to it from the three cities that form its boundaries. First, you need to sum all coordinates and divide the result by their count to take the average:
This will give you a point located in the Atlantic Ocean, somewhere within the triangle: Now you can create vectors anchored in the cities and directed toward the geometric center of the triangle. Vectors are made by subtracting the source from the target point:
Since you subtract complex numbers, every vector is also a complex number made up of two parts. To get your distances, calculate the magnitude of each vector: >>>
These vector lengths don’t reflect meaningful distances but are good approximations for a toy example like this. To represent accurate results in tangible units, you’d have to convert the coordinates from spherical to rectangular first or calculate the distance using the great circle method instead. Translating, Flipping, Scaling, and RotatingIt might be bothering you that the triangle appears in the second quadrant of the Cartesian coordinate system. Let’s move it so that its geometric center aligns with the origin. All three vertices will be translated by the length of the vector indicated by the geometric center but in the opposite direction:
Note that you’re adding two complex numbers together, which performs their element-wise addition. This is an affine transformation since it doesn’t change the shape of the triangle or the relative placement of its vertices: A mirror reflection of the triangle around the real or imaginary axis requires inverting the respective component in its vertices. For example, to flip it horizontally, you’ll have to use the negative of the real part, which corresponds to the horizontal direction. To flip it vertically, you’ll take the negative of the imaginary part:
The latter is essentially the same as calculating a complex number conjugate, so you can call
Naturally, there’s nothing to stop you from applying the symmetry in either direction or both directions simultaneously. In such a case, you can use the unary minus operator in front of the complex number to flip its real and imaginary parts:
Go ahead and fiddle with the different flip combinations using the interactive Jupyter Notebook available in the downloadable materials. Here’s how the triangle will look when you flip it along both axes: Scaling is similar to translating, but instead of adding an offset, you’re going to multiply each vertex by a constant factor, which must be a real number:
Doing so results in multiplying both components of each complex number by the same amount. It should stretch your Bermuda Triangle, making it look bigger on the plot: Multiplying the triangle’s vertices by another complex number, on the other hand, has the effect of rotating it around the coordinate system’s origin. That’s vastly different from how you’d typically multiply vectors by each other. For example, a dot product of two vectors will result in a scalar, while their cross product returns a new vector in three-dimensional space, which is perpendicular to the surface they define. When you multiply the vertices by the imaginary unit, it will rotate the triangle 90° counterclockwise. If you keep repeating it, you’ll eventually arrive where you started: How do you find a specific complex number that will rotate another complex number by any desired angle when both are multiplied? First, take a look at the following table, which summarizes the consecutive rotations by 90°:
When you express the repeated multiplication by For example, the exponent halfway through the first rotation is equal to 0.5 and represents a 45° angle: So, if you know that a power of one represents the right angle, and anything in between scales proportionally, then you can derive this generic formula for arbitrary rotations:
Note that rotation becomes more natural when you express your complex numbers in polar coordinates, which already describe the angle. You can then take advantage of the exponential form to make the calculations more straightforward: There are two ways to rotate a number using polar coordinates:
You can sum angles or multiply your complex number by a unit vector. You’ll learn more about those in the next section. Exploring the Math Module for Complex Numbers: cmathYou’ve already seen that some built-in functions like >>>
Many advanced mathematical functions such as trigonometric, hyperbolic, or logarithmic functions are available in the standard library. Sadly, even if you know everything about the Python The >>>
Note that >>>
There are about half as many functions in Converting Between Rectangular and Polar CoordinatesGeometrically, you can look at a complex number twofold. On the one hand, it’s a point whose horizontal and vertical distances from the origin uniquely identify its location. These are known as rectangular coordinates comprising the real and imaginary parts. On the other hand, you can describe the same point in polar coordinates that also let you find it unambiguously with two distances:
The radius, also known as the modulus, corresponds to the complex number’s magnitude, or the vector’s length. The angle is commonly referred to as the phase or argument of a complex number. It’s useful to express the angle in radians rather than degrees when working with trigonometric functions. Here’s a depiction of a complex number in both coordinate systems: Therefore, a point (3, 2) in the Cartesian coordinate system has a radius of approximately 3.6 and an angle of about 33.7°, or roughly π over 5.4 radians. The conversion between the two coordinate systems is made possible with a couple of functions buried in the >>>
It will return a tuple, where the first element is the radius and the second element is the angle in radians. Note that the radius has the same value as the magnitude, which you can calculate by calling >>>
The angle can be obtained using basic trigonometry since the real part, the imaginary part, and the magnitude together form a right triangle: You can use the inverse trigonometric functions, such as arcsine, either from >>>
There’s one small detail to be careful about when using the arctangent function, though, which led many programming languages to develop an alternative implementation called >>>
Notice how To get degrees instead of radians, you can make the necessary conversion using the >>>
Reversing the process—that is, converting polar to rectangular coordinates—relies on another function. However, you can’t just pass the same
tuple that you got from >>>
It’s a good idea to unpack the tuple first when doing an assignment and give those elements more descriptive names. Now you can call >>>
You might encounter rounding errors along the way while Python makes the calculations. Behind the scenes, it calls the trigonometric functions to retrieve the real and imaginary parts: >>>
Again, it doesn’t matter whether you use Representing Complex Numbers DifferentlyRegardless of the coordinate system, you can express the same complex number in a few mathematically equivalent forms:
This list isn’t exhaustive as there are more representations, such as the matrix representation of complex numbers. Having the choice lets you pick the most convenient one to tackle a given problem. For example, you’re going to need the exponential form to calculate discrete Fourier transform in an upcoming section. Using this form is also suitable for multiplying and dividing complex numbers. Here’s a quick rundown of the individual complex number forms and their coordinates:
The algebraic form is native to Python when you specify complex numbers using their literals. You can also view them as points on a Euclidean plane in the Cartesian or polar coordinate systems. While there aren’t separate representations for the trigonometric or exponential form in Python, you can verify if mathematical principles hold. For example, plugging in Euler’s formula
to the trigonometric form will turn it into the exponential one. You can either call the >>>
All forms are indeed different ways of encoding the same number. However, you can’t compare them directly because of the rounding errors that may occur in the meantime. Use The explanation of why different forms of a complex number are equivalent requires calculus and goes far beyond the scope of this tutorial. However, if you’re interested in math, then you’ll find the connections between different fields of mathematics that are exhibited by complex numbers to be fascinating. Dissecting a Complex Number in PythonYou’ve already learned a bunch about Python complex numbers and have seen preliminary examples. However, before moving further, it’s worthwhile to cover some final topics. In this section, you’re going to look into comparing complex numbers, formatting strings that contain them, and more. Testing Equality of Complex NumbersMathematically, two complex numbers are equal when they have identical values irrespective of the adopted coordinate system. However, converting between polar and rectangular coordinates typically introduces rounding errors in Python, so you need to watch out for minute differences when comparing them. For example, when you consider a point on a unit circle whose radius is equal to one and is tilted at 60°, then the trigonometry works out nicely, making the conversion with pen and paper straightforward: >>>
Even though you know that >>>
Remember to always use them when comparing complex numbers! If the default tolerance isn’t good enough for your calculations, you can change it by specifying additional arguments. Ordering Complex NumbersIf you’re familiar with tuples, then you know that Python can sort them: >>>
By default, the individual tuples are compared left to right: >>>
In the first case, the number >>>
Should the imaginary dimension have more weight than the real one? Should their magnitudes be compared? It’s up to you, and the answers will vary. Since you can’t compare complex numbers
directly, you need to tell Python how to sort them by specifying a custom key function, such as >>>
This will sort the complex numbers by their magnitude in descending order. Formatting Complex Numbers as StringsThere aren’t any format codes specific to complex numbers, but you can format their real and imaginary parts separately using standard codes for floating-point numbers. Below, you’ll find a few techniques that demonstrate this. Some of them will actually apply your format specifier to both the real and imaginary parts in one go. Let’s take the following complex number as an example and format it with two decimal places on both parts: >>>
A quick way to do this is either by calling >>>
If you want more control, for example, to add extra padding around the plus operator, then the f-string will be a better choice: >>>
You can also call >>>
The positional arguments provide a sequence of values, while the keyword arguments let you refer to them by name. Similarly, you can use the string modulo operator ( >>>
However, this uses a different placeholder syntax and is slightly old-fashioned. Creating Your Own Complex Data TypeThe Python data model defines a set of special methods that you can implement to make your classes compatible with certain built-in types. Say you were working with points and vectors and wanted to get the angle between two bound vectors. You might calculate their dot product and do some trigonometry. Alternatively, you can take advantage of complex numbers. Let’s define your classes first:
A To make Python recognize vector instances as complex numbers, you have to supply
The code inside must always return an instance of the >>>
In some cases, you don’t have to make this kind of type casting yourself. Let’s see an example in practice: >>>
You’ve got two vectors identified by four distinct points. Next, you pass them directly to Wasn’t that beautiful? You’ve saved yourself from typing a lot of error-prone code by piggybacking on the complex numbers and a bit of Python magic. Calculating the Discrete Fourier Transform With Complex NumbersWhile you can use real numbers to calculate the sine and cosine coefficients of a periodic function’s frequencies with the Fourier transform, it’s usually more convenient to deal with only one complex coefficient per frequency. The discrete Fourier transform in the complex domain is given by the following formula: For each frequency bin k, it measures the correlation of the signal and a particular sine wave expressed as a complex number in the exponential form. (Thank you, Leonhard Euler!) The angular frequency of the wave can be calculated by multiplying the round angle, which is 2π radians, by k over the number of discrete samples: Coding this in Python looks quite neat when you take advantage of the
This function is a literal transcription of the formulas above. Now you can run a frequency analysis on a sound that you load from an audio file using Python’s To plot the frequency spectrum with Matplotlib, you must know the sampling frequency, which determines your frequency bin resolution as well as the Nyquist limit:
The number of frequency bins in the spectrum is equal to half the samples, while the Nyquist frequency limits the highest frequency you can measure. The transform returns a complex number whose magnitude corresponds to the amplitude of a sine wave at the given frequency, whereas its angle is the phase. Here’s a sample frequency plot of a sound wave comprising three tones—440 Hz, 1.5 kHz, and 5 kHz—having equal amplitudes: Frequency spectrum plotNote this was a purely academic example since calculating the discrete Fourier transform with nested iterations has O(n2) time complexity, making it unusable in practice. For real-life applications, you want to use the fast Fourier transform (FFT) algorithm best implemented in a C library, such as the FFT in SciPy. ConclusionThe ease of using complex numbers in Python makes them a surprisingly fun and practical tool. You saw two-dimensional vectors implemented practically for free, and you were able to analyze sound frequencies thanks to them. Complex numbers let you elegantly express mathematical formulas in code without much boilerplate syntax standing in the way. In this tutorial, you learned how to:
What has your experience been with Python complex numbers so far? Were you ever intimidated by them? What other interesting problems do you think they’ll let you solve? You can click the link below to get the full source code for this tutorial: |