Complex Numbers in Python

Learn how Python's built-in complex number type represents values with real and imaginary parts, how to perform arithmetic, and when to use the cmath module.

5 min read

Python complex numbers are the third and final pillar of the language's built-in numeric type system, joining integers and floats to cover the full spectrum of numbers that programs commonly need. A complex number combines a real part and an imaginary part into a single value, written with a j suffix on the imaginary component, as in 3 + 4j. This is not a niche feature provided by an external library. It is a first-class, built-in type that participates naturally in Python's arithmetic, attribute access, and function dispatch systems. For beginners who may later explore scientific computing, signal processing, or electrical engineering, Python's native complex number support means you can start experimenting with complex arithmetic from day one without installing anything extra.

The complex type rounds out the numeric trio. If you have read about the integer data type and the float data type, you know that integers handle unlimited-precision whole numbers while floats handle IEEE 754 decimal approximations. Complex numbers fill the remaining gap: values that live on the two-dimensional complex plane, with both a horizontal real coordinate and a vertical imaginary coordinate. This article explains how to create complex numbers, access their components, perform arithmetic on them, and use the cmath module when you need mathematical functions beyond the basics.

Creating complex numbers in Python

The most direct way to create a complex number is to write a literal with the j suffix attached to a numeric value. When Python encounters a number followed immediately by j, with no space between them, it interprets that number as the imaginary coefficient. Writing 4j creates a complex number with a real part of zero and an imaginary part of four. You can also write the real part explicitly, as in 3 + 4j, which Python parses into a complex number with a real part of 3.0 and an imaginary part of 4.0. Both j and J are accepted, though lowercase j is the convention used throughout the Python standard library and most third-party code.

The complex constructor function provides a second way to create complex numbers programmatically. Calling complex with two numeric arguments creates a complex number from those real and imaginary parts. Calling complex with a single string argument like "3+4j" parses the string and returns the corresponding complex number. This is particularly useful when reading complex values from configuration files, user input, or data formats that store numbers as text. Calling complex with no arguments returns 0j, and calling it with a single numeric argument returns a complex number with that value as the real part and zero as the imaginary part.

pythonpython
a = 3 + 4j
b = complex(1.5, -2.5)
c = complex("5+12j")
d = complex(7)
e = complex()

The five variables above demonstrate the variety of creation patterns. The first uses a literal. The second uses two float arguments. The third parses a string. The fourth provides only a real part. The fifth returns zero. All five are valid complex numbers that support the same set of operations and attributes.

Accessing parts and computing magnitude

Every complex number object exposes its real and imaginary components through two attributes named real and imag. These attributes always return floating-point values, even if you created the complex number from integer literals. Reading them does not modify the original complex number in any way. It simply returns the two components that Python stores internally as double-precision floats. This consistency with the float type means that complex numbers share the same IEEE 754 precision characteristics, including the presence of special values like infinity and NaN in either component.

The built-in abs function, when given a complex number argument, returns the magnitude, also called the modulus. For a complex number a plus bj, the magnitude is defined as the square root of a squared plus b squared. Geometrically, this is the distance from the origin to the point a, b on the complex plane. The same abs function that returns a positive integer for negative five and a float for negative pi returns a float magnitude for a complex number. This is a good example of Python's polymorphic design: one function name, different meaning depending on the type, all internally consistent.

pythonpython
z = 3 + 4j
print(z.real)
print(z.imag)
print(abs(z))

Running this code prints 3.0, then 4.0, then 5.0. The magnitude of a 3-4-5 right triangle appears naturally because the real and imaginary parts form the two shorter sides of a right triangle on the complex plane, and the magnitude is the length of the hypotenuse.

Arithmetic operations on complex numbers

Complex numbers support all the standard arithmetic operators that work on integers and floats. Addition, subtraction, multiplication, and division all follow the mathematical rules you would expect, with Python handling the cross-terms that arise when multiplying two binomials containing the imaginary unit. The power operator works correctly, including raising a complex number to an integer exponent. Two operators that do not apply to complex numbers are floor division and the modulo operator. Attempting to use either of them with a complex operand raises a TypeError because neither operation has a mathematically meaningful definition on the complex plane.

When you mix complex numbers with integers or floats in the same expression, Python automatically converts the narrower type to the wider one before performing the operation. Adding an integer to a complex number yields a complex result where the integer contributes only to the real part. This implicit widening is an instance of Python's type coercion rules, which are explored in more detail in the article on implicit and explicit type conversion. The key takeaway for complex numbers is that you can freely mix them with other numeric types without writing explicit conversion code.

The cmath module for advanced mathematics

The math module that provides trigonometric, logarithmic, and exponential functions for floats does not work with complex numbers. Calling math.sqrt with a negative argument raises a ValueError. For complex-aware versions of these functions, Python provides the cmath module, which mirrors the math module's function names but accepts and returns complex numbers. Importing cmath and calling cmath.sqrt on a negative real number returns a complex result with a zero real part and a positive imaginary part, which is the mathematically correct principal square root.

Beyond the familiar square root and exponential functions, cmath includes functions specific to complex analysis. The cmath.phase function returns the phase angle of a complex number in radians, which is the angle between the positive real axis and the line from the origin to the point. The cmath.polar function converts a complex number from rectangular to polar coordinates, returning a tuple of magnitude and angle. The cmath.rect function does the reverse, converting polar coordinates back to a complex number. Together, these three functions let you switch between the two standard representations of complex numbers as your application requires.

Comparison limitations and immutability

Complex numbers support equality and inequality but do not support ordering. The table below summarizes which comparison operators are available for each numeric type:

OperatorintfloatcomplexMeaning
==yesyesyesEqual value
!=yesyesyesNot equal value
<yesyesnoLess than
>yesyesnoGreater than
<=yesyesnoLess than or equal
>=yesyesnoGreater than or equal

Complex numbers support equality comparison with the double-equals operator, which returns True only when both the real and imaginary parts are exactly equal. The not-equals operator returns True when either part differs. However, complex numbers do not support ordering comparisons. Any attempt to use less-than or greater-than on complex numbers raises a TypeError because there is no mathematically consistent way to decide whether one point on a two-dimensional plane is less than another. Python deliberately blocks these comparisons rather than providing an arbitrary ordering that might appear to work but would produce incorrect mathematical results in some contexts.

Like integers and floats, complex numbers are immutable. Once you create a complex number, you cannot change its real or imaginary parts. Any operation that appears to modify a complex number actually creates and returns a new complex number object. This immutability is shared across all of Python's numeric types and is a foundational property that makes reasoning about numeric code easier because you never need to worry about a number changing unexpectedly while another part of your program holds a reference to it. The article on immutable and mutable data types covers this distinction across all of Python's built-in types.

Rune AI

Rune AI

Key Insights

  • Python complex numbers are written as a+bj where j represents the imaginary unit.
  • Access the real and imaginary parts through .real and .imag attributes.
  • Use abs() for magnitude and conjugate() for the complex conjugate.
  • Import the cmath module for advanced functions like phase, polar coordinates, and complex square roots.
  • Complex numbers are immutable and do not support ordering comparisons like less-than or greater-than.
RunePowered by Rune AI

Frequently Asked Questions

What is the j suffix in Python complex numbers?

In Python, complex numbers use j for the imaginary unit instead of the mathematical i. This convention comes from electrical engineering where i is reserved for current. You write the imaginary part followed by j with no space, like 3+4j. Both lowercase j and uppercase J work, though lowercase is standard in Python code.

Can I use complex numbers for everyday Python programming?

Most beginner and general-purpose programs do not need complex numbers. They are primarily useful in scientific computing, signal processing, electrical engineering, physics simulations, and computer graphics where quantities naturally have real and imaginary components. Having them built into Python without imports means they are available for mathematical exploration at any time.

How do I extract the real and imaginary parts from a complex number?

Every complex number object has .real and .imag attributes that return the real and imaginary parts as floats. For example, (3+4j).real returns 3.0 and (3+4j).imag returns 4.0. The built-in abs() function returns the magnitude, and the conjugate() method returns the complex conjugate with the imaginary part sign flipped.

Conclusion

Python's built-in complex number type makes mathematical and scientific programming more accessible by eliminating the need for external libraries for basic complex arithmetic. Even if complex numbers are not part of your daily work, knowing the type exists and how to work with it completes your understanding of Python's three numeric pillars: integers, floats, and complex numbers.