# Python Complex Numbers

A Complex Number is any number of the form `a + bj`, where `a` and `b` are real numbers, and `j*j` = -1.

In Python, there are multiple ways to create such a Complex Number.

## Create a Complex Number in Python

• We can directly use the syntax `a + bj` to create a Complex Number.
```>>> a = 4 + 3j
>>> print(a)
(4+3j)
>>> print(type(a))
<class 'complex'>
```
• We can also use the `complex` Class to create a complex number
```>>> a = complex(4, 3)
>>> print(type(a))
<class 'complex'>
>>> print(a)
(4+3j)
```

### Real and Imaginary Parts in Complex Number

Every complex number (`a + bj`) has a real part (`a`), and an imaginary part (`b`).

To get the real part, use `number.real`, and to get the imaginary part, use `number.imag`.

```>>> a
(4+3j)
>>> a.real
4.0
>>> a.imag
3.0
```

### Conjugate of a Complex Number

The conjugate of a complex number `a + bj` is defined as `a - bj`. We can also use `number.conjugate()`method to get the conjugate.

```>>> a
(4 + 3j)
>>> a.conjugate()
(4-3j)
```

## Arithmetic Operations on Complex Numbers

Similar to real numbers, Complex Numbers also can be added, subtracted, multiplied and divided. Let us look at how we could do this in Python.

```a = 1 + 2j
b = 2 + 4j
print('Addition =', a + b)
print('Subtraction =', a - b)
print('Multiplication =', a * b)
print('Division =', a / b)
```

Output:

```Addition = (3+6j)
Subtraction = (-1-2j)
Multiplication = (-6+8j)
Division = (2+0j)
```

NOTE: Unlike real numbers, we cannot compare two complex numbers. We can only compare their real and imaginary parts individually, since they are real numbers. The below snippet proves this.

```>>> a
(4+3j)
>>> b
(4+6j)
>>> a < b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'complex' and 'complex'
```

## Phase (Argument) of a Complex Number

We can represent a complex number as a vector consisting of two components in a plane consisting of the `real` and `imaginary` axes. Therefore, the two components of the vector are it’s real part and it’s imaginary part.

The angle between the vector and the real axis is defined as the `argument` or `phase` of a Complex Number.

It is formally defined as :

phase(number) = arctan(imaginary_part / real_part)

where the arctan function is the tan inverse mathematical function.

In Python, we can get the phase of a Complex Number using the `cmath` module for complex numbers. We can also use the `math.arctan` function and get the phase from it’s mathematical definition.

```import cmath
import math

num = 4 + 3j

# Using cmath module
p = cmath.phase(num)
print('cmath Module:', p)

# Using math module
p = math.atan(num.imag/num.real)
print('Math Module:', p)
```

Output:

```cmath Module: 0.6435011087932844
Math Module: 0.6435011087932844
```

Note that this function returns the phase angle in `radians`, so if we need to convert to `degrees`, we can use another library like `numpy`.

```import cmath
import numpy as np

num = 4 + 3j

# Using cmath module
p = cmath.phase(num)
print('cmath Module in Radians:', p)
print('Phase in Degrees:', np.degrees(p))
```

Output:

```cmath Module in Radians: 0.6435011087932844
Phase in Degrees: 36.86989764584402
```

## Rectangular and Polar Coordinates

A Complex Number can be written in Rectangular Coordinate or Polar Coordinate formats using the `cmath.rect()` and `cmath.polar()` functions.

```>>> import cmath
>>> a = 3 + 4j
>>> polar_coordinates = cmath.polar(a)
>>> print(polar_coordinates)
(5.0, 0.9272952180016122)

>>> modulus = abs(a)
>>> phase = cmath.phase(a)
>>> rect_coordinates = cmath.rect(modulus, phase)
>>> print(rect_coordinates)
(3.0000000000000004+3.9999999999999996j)
```

## Constants in the cmath Module

There are special constants in the cmath module. Some of them are listed below.

```print('π =', cmath.pi)
print('e =', cmath.e)
print('tau =', cmath.tau)
print('Positive infinity =', cmath.inf)
print('Positive Complex infinity =', cmath.infj)
print('NaN =', cmath.nan)
print('NaN Complex =', cmath.nanj)
```

Output:

```π = 3.141592653589793
e = 2.718281828459045
tau = 6.283185307179586
Positive infinity = inf
Positive Complex infinity = infj
NaN = nan
NaN Complex = nanj
```

## Trigonometric Functions

Trigonometric functions for a complex number are also available in the `cmath` module.

```import cmath

a = 3 + 4j

print('Sine:', cmath.sin(a))
print('Cosine:', cmath.cos(a))
print('Tangent:', cmath.tan(a))

print('ArcSin:', cmath.asin(a))
print('ArcCosine:', cmath.acos(a))
print('ArcTan:', cmath.atan(a))
```

Output:

```Sine: (3.853738037919377-27.016813258003936j)
Cosine: (-27.034945603074224-3.8511533348117775j)
Tangent: (-0.0001873462046294784+0.999355987381473j)
ArcSin: (0.6339838656391766+2.305509031243477j)
ArcCosine: (0.9368124611557198-2.305509031243477j)
ArcTan: (1.4483069952314644+0.15899719167999918j)
```

## Hyperbolic Functions

Similar to Trigonometric functions, Hyperbolic Functions for a complex number are also available in the `cmath` module.

```import cmath

a = 3 + 4j

print('Hyperbolic Sine:', cmath.sinh(a))
print('Hyperbolic Cosine:', cmath.cosh(a))
print('Hyperbolic Tangent:', cmath.tanh(a))

print('Inverse Hyperbolic Sine:', cmath.asinh(a))
print('Inverse Hyperbolic Cosine:', cmath.acosh(a))
print('Inverse Hyperbolic Tangent:', cmath.atanh(a))
```

Output:

```Hyperbolic Sine: (-6.5481200409110025-7.61923172032141j)
Hyperbolic Cosine: (-6.580663040551157-7.581552742746545j)
Hyperbolic Tangent: (1.000709536067233+0.00490825806749606j)
Inverse Hyperbolic Sine: (2.2999140408792695+0.9176168533514787j)
Inverse Hyperbolic Cosine: (2.305509031243477+0.9368124611557198j)
Inverse Hyperbolic Tangent: (0.11750090731143388+1.4099210495965755j)
```

## Exponential and Logarithmic Functions

```import cmath
a = 3 + 4j
print('e^c =', cmath.exp(a))
print('log2(c) =', cmath.log(a, 2))
print('log10(c) =', cmath.log10(a))
print('sqrt(c) =', cmath.sqrt(a))
```

Output:

```e^c = (-13.128783081462158-15.200784463067954j)
log2(c) = (2.321928094887362+1.3378042124509761j)
log10(c) = (0.6989700043360187+0.4027191962733731j)
sqrt(c) = (2+1j)
```

## Miscellaneous Functions

There are some miscellaneous functions to check if a complex number is finite, infinite or `nan`. There is also a function to check if two complex numbers are close.

```>>> print(cmath.isfinite(2 + 2j))
True

>>> print(cmath.isfinite(cmath.inf + 2j))
False

>>> print(cmath.isinf(2 + 2j))
False

>>> print(cmath.isinf(cmath.inf + 2j))
True

>>> print(cmath.isinf(cmath.nan + 2j))
False

>>> print(cmath.isnan(2 + 2j))
False

>>> print(cmath.isnan(cmath.inf + 2j))
False

>>> print(cmath.isnan(cmath.nan + 2j))
True

>>> print(cmath.isclose(2+2j, 2.01+1.9j, rel_tol=0.05))
True

>>> print(cmath.isclose(2+2j, 2.01+1.9j, abs_tol=0.005))
False
```

## Conclusion

We learned about the Complex Numbers module, and various functions associated with the `cmath` module.