Back to Blog
Python

Python Complex Number Operations: Syntax and Practical Use

python complex number operations: Learn how to create, manipulate, and format complex numbers in Python, including arithmetic, cmath functions, and common performance...

complex numberscmath modulePython numeric typesarithmetic operationsperformance
Illustration of a complex plane with Python code snippets showing arithmetic operations on complex numbers.

python complex number operations requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

Python's built-in complex type provides direct support for complex number operations, including arithmetic, conversion, and formatting. The language's behavior differs from many other languages in a few important ways, especially around comparison and rounding, so it helps to know exactly what the standard library does before relying on it in numerical code.

Creating Complex Numbers in Python

You can create a complex number either with the complex() constructor or with the literal syntax using j as the imaginary unit:

a = 3 + 4j b = complex(3, 4)

Both produce the same value. The literal form is usually clearer, but the constructor is useful when the real and imaginary parts come from variables or when you need to parse a string:

real = 2.5 imag = -1.5 c = complex(real, imag)

The constructor also accepts a string, but only if it is in a format that Python's parser recognizes, such as "3+4j". Passing a string that contains spaces or an unsupported format raises ValueError.

You can access the real and imaginary parts as attributes:

print(c.real) # 2.5 print(c.imag) # -1.5

These attributes are read-only. To change a complex number, you must create a new one.

Arithmetic Operations and Built-in Functions

The standard arithmetic operators work with complex numbers:

z1 = 1 + 2j z2 = 3 - 4j print(z1 + z2) # (4-2j) print(z1 - z2) # (-2+6j) print(z1 * z2) # (11+2j) print(z1 / z2) # (-0.2+0.4j)

Division uses the standard formula and handles the conjugate automatically. The result is always a complex object, even when the imaginary part is zero.

The built-in abs() returns the magnitude (modulus) of the complex number:

z = 3 + 4j print(abs(z)) # 5.0

The pow() function and the ** operator support complex exponents, but the result follows the standard mathematical rules, including the principal branch for non-integer powers. For example:

z = 1 + 1j print(z**2) # 2j print(z**0.5) # (1.098684... + 0.455089...j)

The built-in round() works on complex numbers, but it rounds each part independently and returns a complex number. That is often not what you want for numerical algorithms that require a single rounding rule.

Using the cmath Module for Advanced Math

The cmath module provides mathematical functions that accept complex numbers, including exponentials, logarithms, trigonometric functions, and hyperbolic functions. These functions return complex numbers even when the result could be expressed as a real number.

import cmath z = 1 + 2j print(cmath.exp(z)) # (-1.131... + 2.471...j) print(cmath.log(z)) # (0.804... + 1.107...j) print(cmath.sqrt(z)) # (1.272... + 0.786...j) print(cmath.sin(z)) # (3.165... + 1.892...j)

The cmath module also exposes phase() and polar() for working with polar coordinates:

r, theta = cmath.polar(z) print(r, theta) # 2.236... 1.107... print(cmath.rect(r, theta)) # (1+2j)

polar() returns a tuple of magnitude and phase angle in radians. rect() converts back to rectangular form. These functions are useful when you need to rotate a vector or compute angles.

Comparisons and Ordering Limitations

Complex numbers do not support the standard ordering operators <, >, <=, or >=. This is a deliberate design choice because there is no natural total order on the complex plane that is consistent with arithmetic operations. If you attempt to compare two complex numbers directly, Python raises a TypeError.

z1 = 1 + 2j z2 = 2 + 1j # z1 < z2 # TypeError: '<' not supported between instances of 'complex' and 'complex'

Equality (== and !=) works and compares both real and imaginary parts. If you need to sort a list of complex numbers, you must provide a key function, such as magnitude or phase:

points = [3 + 4j, 1 + 1j, 2 - 2j] sorted_by_magnitude = sorted(points, key=abs)

This limitation is important to remember when using complex numbers in data structures that rely on ordering, like bisect or certain tree-based collections.

Performance Considerations for Complex Operations

Complex arithmetic in Python is implemented in C and is reasonably efficient, but there are a few performance-related behaviors to keep in mind.

First, each operation creates a new complex object. In tight loops, this allocation overhead can become significant. If you are doing many operations on the same values, consider using numpy arrays of complex numbers, which store the data in a contiguous block and perform vectorized operations without per-element Python object overhead.

Second, the cmath functions are not vectorized. Calling cmath.sqrt on a large list of complex numbers involves a Python loop and function call per element. Using numpy's sqrt on a complex array is typically much faster for large datasets.

Third, the complex type is immutable, so there is no in-place operation. Every += or *= creates a new object. This is the same as for int and float, so it should not be surprising, but it matters when you are accumulating results in a loop.

If you are working with large numerical datasets, profile your code before optimizing. The built-in complex type is fine for most applications, but vectorized libraries become necessary when you move into scientific computing or signal processing.

Common Pitfalls and How to Avoid Them

One common mistake is assuming that the imaginary unit is i instead of j. Python uses j to avoid conflicts with variable names. Writing 3 + 4i raises a SyntaxError.

Another pitfall is using round() on a complex number without understanding its behavior. round(1.5 + 2.5j) returns (2+2j) because Python's rounding for floats is banker's rounding, and it applies independently to each part. If you need a different rounding rule, apply it to the real and imaginary parts separately.

When converting a complex number to a string, Python uses the repr() format, which includes parentheses and a j suffix. For user-facing output, you may want to format it manually:

z = 3 - 4j print(f"{z.real:.2f} {z.imag:+.2f}j") # "3.00 -4.00j"

This avoids the parentheses and gives you control over the number of decimal places.

Finally, remember that division by zero for complex numbers raises ZeroDivisionError, just like real numbers. However, the result of dividing a nonzero complex number by zero is not defined, so Python does not return infinity or NaN.

Using Complex Numbers in Real-World Code

Complex numbers appear naturally in signal processing, control systems, and physics simulations. In Python, you can store them in lists, tuples, or dictionaries, and they work with the standard library's data structures. For example, you can use a complex number to represent a point in a 2D plane and rotate it by multiplying by a unit complex number:

point = 1 + 0j rotation = 0.707 + 0.707j # 45 degrees rotated = point * rotation

This is a compact way to express rotation without trigonometry.

When you need to pass complex numbers to external libraries, check whether the library expects complex objects or a pair of floats. Many scientific libraries accept both, but some older C extensions require a specific representation.

For serialization, the json module does not natively support complex numbers. You will need to convert them to a list or a custom format:

import json z = 3 + 4j data = {"real": z.real, "imag": z.imag} json.dumps(data)

This is a common integration point when storing complex data in a database or sending it over an API.

python complex number operations: Practical Usage and Code E | RYUSLOG DEV