# Introduction

`Complex numbers` are not complicated.
They just need a less alarming name.

They are so useful, especially in engineering and science (_everything from JPEG compression to quantum mechanics_), that Python includes [`complex`][complex] as a standard numeric type alongside integers ([`int`s][ints]) and floating-point numbers ([`float`s][floats]).

A `complex` value in Python is essentially a pair of floating-point numbers:

```python
>>> my_complex = 5.443+6.77j
(5.443+6.77j)
```

These are called the "real" and "imaginary" parts.
You may have heard that "`i` (or `j`) is the square root of -1".
For now, all this means is that the imaginary part _by definition_ satisfies the equality `1j * 1j == -1`.
This is a simple idea, but it leads to interesting mathematical consequences.

In Python, the "imaginary" part is designated with `j` (_not `i` as you would see in math textbooks_), and
the `j` must immediately follow a number, to prevent Python seeing it as a variable name:


```python
>>> j
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined

>>> 1j
1j

>>> type(1j)
<class 'complex'>
```


There are two common ways to create complex numbers.

1) The [`complex(real, imag)`][complex] constructor takes two `float` parameters:

    ```python
    >>> z1 = complex(1.5, 2.0)
    >>> z1
    (1.5+2j)
    ```

    The constructor can also parse string input.
    This has the odd limitation that it fails if the string contains spaces.

    ```python
    >>> complex('4+2j')
    (4+2j)
    
    >>> complex('4 + 2j')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: complex() arg is a malformed string
    ```


2) The complex number can be specified as `<real part> + <complex part>j` literal, or just `<complex part>j` if the real part is zero:


    ```python
    >>> z2 = 2.0 + 1.5j
    >>> z2
    (2+1.5j)
    ```
    The end result is identical to using the `complex()` constructor.


## Arithmetic

Most of the [`operators`][operators] used with floats and ints also work with complex numbers.

Integer division is _**not**_ possible on complex numbers, so the `//` and `%` operators and `divmod()` functions will fail for the complex number type.

Explaining the rules for complex number multiplication and division is out of scope for this concept (_and you are unlikely to have to perform those operations "by hand" very often_).

Any [mathematical][math-complex] or [electrical engineering][engineering-complex] introduction to complex numbers will cover these scenarios, should you want to dig into the topic.

The Python standard library has a [`math`][math-module] module full of useful functionality for working with real numbers and the [`cmath`][cmath] module is its equivalent for working with complex numbers.


[cmath]: https://docs.python.org/3/library/cmath.html
[complex]: https://docs.python.org/3/library/functions.html#complex
[engineering-complex]: https://www.khanacademy.org/science/electrical-engineering/ee-circuit-analysis-topic/ee-ac-analysis/v/ee-complex-numbers
[floats]: https://docs.python.org/3/library/functions.html#float
[ints]: https://docs.python.org/3/library/functions.html#int
[math-complex]: https://www.nagwa.com/en/videos/143121736364/
[math-module]: https://docs.python.org/3/library/math.html
[operators]: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex
