The cmath
module is similar to the math
module, but defines functions appropriately for the complex plane.
First of all, complex numbers are a numeric type that is part of the Python language itself rather than being provided by a library class. Thus we don't need to import cmath
for ordinary arithmetic expressions.
Note that we use j
(or J
) and not i
.
z = 1 + 3j
We must use 1j
since j
would be the name of a variable rather than a numeric literal.
1j * 1j
Out: (-1+0j)
1j ** 1j
# Out: (0.20787957635076193+0j) # "i to the i" == math.e ** -(math.pi/2)
We have the real
part and the imag
(imaginary) part, as well as the complex conjugate
:
# real part and imaginary part are both float type
z.real, z.imag
# Out: (1.0, 3.0)
z.conjugate()
# Out: (1-3j) # z.conjugate() == z.real - z.imag * 1j
The built-in functions abs
and complex
are also part of the language itself and don't require any import:
abs(1 + 1j)
# Out: 1.4142135623730951 # square root of 2
complex(1)
# Out: (1+0j)
complex(imag=1)
# Out: (1j)
complex(1, 1)
# Out: (1+1j)
The complex
function can take a string, but it can't have spaces:
complex('1+1j')
# Out: (1+1j)
complex('1 + 1j')
# Exception: ValueError: complex() arg is a malformed string
But for most functions we do need the module, for instance sqrt
:
import cmath
cmath.sqrt(-1)
# Out: 1j
Naturally the behavior of sqrt
is different for complex numbers and real numbers. In non-complex math
the square root of a negative number raises an exception:
import math
math.sqrt(-1)
# Exception: ValueError: math domain error
Functions are provided to convert to and from polar coordinates:
cmath.polar(1 + 1j)
# Out: (1.4142135623730951, 0.7853981633974483) # == (sqrt(1 + 1), atan2(1, 1))
abs(1 + 1j), cmath.phase(1 + 1j)
# Out: (1.4142135623730951, 0.7853981633974483) # same as previous calculation
cmath.rect(math.sqrt(2), math.atan(1))
# Out: (1.0000000000000002+1.0000000000000002j)
The mathematical field of complex analysis is beyond the scope of this example, but many functions in the complex plane have a "branch cut", usually along the real axis or the imaginary axis. Most modern platforms support "signed zero" as specified in IEEE 754, which provides continuity of those functions on both sides of the branch cut. The following example is from the Python documentation:
cmath.phase(complex(-1.0, 0.0))
# Out: 3.141592653589793
cmath.phase(complex(-1.0, -0.0))
# Out: -3.141592653589793
The cmath
module also provides many functions with direct counterparts from the math
module.
In addition to sqrt
, there are complex versions of exp
, log
, log10
, the trigonometric functions and their inverses (sin
, cos
, tan
, asin
, acos
, atan
), and the hyperbolic functions and their inverses (sinh
, cosh
, tanh
, asinh
, acosh
, atanh
). Note however there is no complex counterpart of math.atan2
, the two-argument form of arctangent.
cmath.log(1+1j)
# Out: (0.34657359027997264+0.7853981633974483j)
cmath.exp(1j * cmath.pi)
# Out: (-1+1.2246467991473532e-16j) # e to the i pi == -1, within rounding error
The constants pi
and e
are provided. Note these are float
and not complex
.
type(cmath.pi)
# Out: <class 'float'>
The cmath
module also provides complex versions of isinf
, and (for Python 3.2+) isfinite
. See "Infinity and NaN". A complex number is considered infinite if either its real part or its imaginary part is infinite.
cmath.isinf(complex(float('inf'), 0.0))
# Out: True
Likewise, the cmath
module provides a complex version of isnan
. See "Infinity and NaN". A complex number is considered "not a number" if either its real part or its imaginary part is "not a number".
cmath.isnan(0.0, float('nan'))
# Out: True
Note there is no cmath
counterpart of the math.inf
and math.nan
constants (from Python 3.5 and higher)
cmath.isinf(complex(0.0, math.inf))
# Out: True
cmath.isnan(complex(math.nan, 0.0))
# Out: True
cmath.inf
# Exception: AttributeError: module 'cmath' has no attribute 'inf'
In Python 3.5 and higher, there is an isclose
method in both cmath
and math
modules.
z = cmath.rect(*cmath.polar(1+1j))
z
# Out: (1.0000000000000002+1.0000000000000002j)
cmath.isclose(z, 1+1j)
# True