|
1 |
| -#TODO: Add about for this concept. |
| 1 | +# About |
| 2 | + |
| 3 | +`Complex numbers` are not complicated. |
| 4 | +They just need a less alarming name. |
| 5 | + |
| 6 | +They are so useful, especially in engineering and science, that Python includes [`complex`][complex] as a standard numeric type alongside integers ([`int`s][ints]) and floating-point numbers ([`float`s][floats]). |
| 7 | + |
| 8 | + |
| 9 | +## Basics |
| 10 | + |
| 11 | +A `complex` value in Python is essentially a pair of floating-point numbers. |
| 12 | +These are called the "real" and "imaginary" parts, for unfortunate historical reasons. |
| 13 | +Again, it is best to focus on the underlying simplicity and not the strange names. |
| 14 | + |
| 15 | +There are two common ways to create complex numbers. |
| 16 | + |
| 17 | +1) The [`complex(real, imag)`][complex] constructor takes two `float` parameters: |
| 18 | + |
| 19 | +```python |
| 20 | +>>> z1 = complex(1.5, 2.0) |
| 21 | +>>> z1 |
| 22 | +(1.5+2j) |
| 23 | +``` |
| 24 | + |
| 25 | +The constructor can also parse string input. |
| 26 | +This has the odd limitation that it fails if the string contains spaces. |
| 27 | + |
| 28 | +```python |
| 29 | +>>> complex('4+2j') |
| 30 | +(4+2j) |
| 31 | + |
| 32 | +>>> complex('4 + 2j') |
| 33 | +Traceback (most recent call last): |
| 34 | + File "<stdin>", line 1, in <module> |
| 35 | +ValueError: complex() arg is a malformed string |
| 36 | +``` |
| 37 | + |
| 38 | + |
| 39 | +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: |
| 40 | + |
| 41 | + |
| 42 | +```python |
| 43 | +>>> z2 = 2.0 + 1.5j |
| 44 | +>>> z2 |
| 45 | +(2+1.5j) |
| 46 | +``` |
| 47 | +The end result is identical to using the `complex()` constructor. |
| 48 | + |
| 49 | + |
| 50 | +There are two rules for that imaginary part of the complex number: |
| 51 | + |
| 52 | + |
| 53 | +- It is designated with `j` (not `i` as you may see in math textbooks). |
| 54 | + |
| 55 | +- The `j` must immediately follow a number, to prevent Python seeing it as a variable name. If necessary, use `1j`. |
| 56 | + |
| 57 | +```python |
| 58 | +>>> j |
| 59 | +Traceback (most recent call last): |
| 60 | + File "<stdin>", line 1, in <module> |
| 61 | +NameError: name 'j' is not defined |
| 62 | + |
| 63 | +>>> 1j |
| 64 | +1j |
| 65 | + |
| 66 | +>>> type(1j) |
| 67 | +<class 'complex'> |
| 68 | +``` |
| 69 | + |
| 70 | +Most engineers are happy with `j`. |
| 71 | +Most scientists and mathematicians prefer the mathematical notation `i` for _imaginary_, but that notation conflicts with the use of `i` to mean _current_ in Electrical Engineering. |
| 72 | +So in designing Python, the Electrical Engineers won. |
| 73 | + |
| 74 | + |
| 75 | +To access the parts of a complex number individually: |
| 76 | + |
| 77 | +```python |
| 78 | +>>> z2.real |
| 79 | +2.0 |
| 80 | +>>> z2.imag |
| 81 | +1.5 |
| 82 | +``` |
| 83 | + |
| 84 | +Either part can be zero and mathematicians may then talk of the number being "wholly real" or "wholly imaginary". |
| 85 | +However, it is still a complex number in Python: |
| 86 | + |
| 87 | + |
| 88 | +```python |
| 89 | +>>> complex(0, 1) |
| 90 | +1j |
| 91 | +>>> type(complex(0, 1)) |
| 92 | +<class 'complex'> |
| 93 | + |
| 94 | +>>> complex(1, 0) |
| 95 | +(1+0j) |
| 96 | +``` |
| 97 | + |
| 98 | +You may have heard that "`i` (or `j`) is the square root of -1". |
| 99 | + |
| 100 | +For now, all this means is that the imaginary part _by definition_ satisfies the equality |
| 101 | +```python |
| 102 | +1j * 1j == -1 # => True |
| 103 | +``` |
| 104 | + |
| 105 | +This is a simple idea, but it leads to interesting consequences. |
| 106 | + |
| 107 | +## Arithmetic |
| 108 | + |
| 109 | +Most of the [`operators`][operators] used with floats and ints also work with complex numbers: |
| 110 | + |
| 111 | + |
| 112 | +```python |
| 113 | +>>> z1 = (1.5+2j) |
| 114 | +>>> z2 = (2+1.5j) |
| 115 | + |
| 116 | + |
| 117 | +>>> z1 + z2 # addition |
| 118 | +(3.5+3.5j) |
| 119 | + |
| 120 | +>>> z1 - z2 # subtraction |
| 121 | +(-0.5+0.5j) |
| 122 | + |
| 123 | +>>> z1 * z2 # multiplication |
| 124 | +6.25j |
| 125 | + |
| 126 | +>>> z1 / z2 # division |
| 127 | +(0.96+0.28j) |
| 128 | + |
| 129 | +>>> z1 ** 2 # exponentiation |
| 130 | +(-1.75+6j) |
| 131 | + |
| 132 | +>>> 2 ** z1 # another exponentiation |
| 133 | +(0.5188946835878313+2.7804223253571183j) |
| 134 | + |
| 135 | +>>> 1j ** 2 # j * j == -1 |
| 136 | +(-1+0j) |
| 137 | +``` |
| 138 | + |
| 139 | +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_). |
| 140 | + |
| 141 | +Any [mathematical][math-complex] or [electrical engineering][engineering-complex] introduction to complex numbers will cover this, should you want to dig into the topic. |
| 142 | + |
| 143 | +Alternatively, Exercism has a `Complex Numbers` practice exercise where you can implement a complex number class with these operations from first principles. |
| 144 | + |
| 145 | + |
| 146 | +Integer division is ___not___ possible on complex numbers, so the `//` and `%` operators and `divmod()` functions will fail for the complex number type. |
| 147 | + |
| 148 | + |
| 149 | +There are two functions implemented for numeric types that are very useful when working with complex numbers: |
| 150 | + |
| 151 | +- `<complex number>.conjugate()` simply flips the sign of the imaginary part of a complex number (_from + to - or vice-versa_). |
| 152 | + - Because of the way complex multiplication works, this is more useful than you might think. |
| 153 | +- `abs(<complex number>)` is guaranteed to return a real number with no imaginary part. |
| 154 | + |
| 155 | + |
| 156 | +```python |
| 157 | +>>> z1 |
| 158 | +(1.5+2j) |
| 159 | + |
| 160 | +>>> z1.conjugate() # flip the z1.imag sign |
| 161 | +(1.5-2j) |
| 162 | + |
| 163 | +>>> abs(z1) # sqrt(z1.real ** 2 + z1.imag ** 2) |
| 164 | +2.5 |
| 165 | +``` |
| 166 | + |
| 167 | +## The `cmath` module |
| 168 | + |
| 169 | +The Python standard library has a [`math`][math-module] module full of useful functionality for working with real numbers. |
| 170 | + |
| 171 | +It also has an equivalent [`cmath`][cmath] module for working with complex numbers. |
| 172 | + |
| 173 | + |
| 174 | +We encourage you to read through the module and experiment, but the main categories are: |
| 175 | + |
| 176 | +- Conversion between Cartesian and polar coordinates, |
| 177 | +- Exponential and log functions, |
| 178 | +- Trigonometric functions, |
| 179 | +- Hyperbolic functions, |
| 180 | +- Classification functions, and |
| 181 | +- Useful constants. |
| 182 | + |
| 183 | +Here is an example using some constants: |
| 184 | + |
| 185 | +```python |
| 186 | +>>> import cmath |
| 187 | + |
| 188 | +>>> euler = cmath.exp(1j * cmath.pi) # Euler's equation |
| 189 | + |
| 190 | +>>> euler.real |
| 191 | +-1.0 |
| 192 | +>>> round(euler.imag, 15) # round to 15 decimal places |
| 193 | +0.0 |
| 194 | +``` |
| 195 | + |
| 196 | +So a simple expression with three of the most important constants in nature `e`, `i` (or `j`) and `pi` gives the result `-1`. |
| 197 | +Some people believe this is the most beautiful result in all of mathematics. |
| 198 | +It dates back to around 1740. |
| 199 | + |
| 200 | +----- |
| 201 | + |
| 202 | +## Optional section: a Complex Numbers FAQ |
| 203 | + |
| 204 | +This part can be skipped, unless you are interested. |
| 205 | + |
| 206 | +### Isn't this some strange new piece of pure mathematics? |
| 207 | + |
| 208 | +It was strange and new in the 16th century. |
| 209 | + |
| 210 | +500 years later, it is central to most of engineering and the physical sciences. |
| 211 | + |
| 212 | +### Why would anyone use these? |
| 213 | + |
| 214 | +It turns out that complex numbers are the simplest way to describe anything that rotates or anything with a wave-like property. |
| 215 | +So they are used widely in electrical engineering, audio processing, physics, computer gaming, and navigation - to name only a few applications. |
| 216 | + |
| 217 | +You can see things rotate. |
| 218 | +Complex numbers may not make the world go round, but they are great for explaining _what happens_ as a result of the world going round: look at any satellite image of a major storm. |
| 219 | + |
| 220 | + |
| 221 | +Less obviously, sound is wave-like, light is wave-like, radio signals are wave-like, and even the economy of your home country is at least partly wave-like. |
| 222 | + |
| 223 | + |
| 224 | +A lot of this wave processing can be done with trig functions (`sin()` and `cos()`) but that gets messy quite quickly. |
| 225 | + |
| 226 | +Complex exponentials are ___much___ easier to work with. |
| 227 | + |
| 228 | +### But I don't need complex numbers! |
| 229 | + |
| 230 | + |
| 231 | +Only true if you are living in a cave and foraging for your food. |
| 232 | + |
| 233 | +If you are reading this on any sort of screen, you are utterly dependent on some useful 20th-Century advances made through the use of complex numbers. |
| 234 | + |
| 235 | + |
| 236 | +1. __Semiconductor chips__. |
| 237 | + - These make no sense in classical physics and can only be explained (and designed) by quantum mechanics (QM). |
| 238 | + - In QM, everything is complex-valued by definition. (_its waveforms all the way down_) |
| 239 | + |
| 240 | +2. __The Fast Fourier Transform algorithm__. |
| 241 | + - FFT is an application of complex numbers, and it is in _everything_ connected to sound transmission, audio processing, photos, and video. |
| 242 | + |
| 243 | + -MP3 and other audio formats use FFT for compression, ensuring more audio can fit within a smaller storage space. |
| 244 | + - JPEG compression and MP4 video, among many other image and video formats also use FTT for compression. |
| 245 | + |
| 246 | + - FFT is also deployed in the digital filters that allow cellphone towers to separate your personal cell signal from everyone else's. |
| 247 | + |
| 248 | + |
| 249 | +So, you are probably using technology that relies on complex number calculations thousands of times per second. |
| 250 | + |
| 251 | + |
| 252 | +[complex]: https://docs.python.org/3/library/functions.html#complex |
| 253 | +[cmath]: https://docs.python.org/3/library/cmath.html |
| 254 | +[operators]: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex |
| 255 | +[math-module]: https://docs.python.org/3/library/math.html |
| 256 | +[math-complex]: https://www.nagwa.com/en/videos/143121736364/ |
| 257 | +[engineering-complex]: https://www.khanacademy.org/science/electrical-engineering/ee-circuit-analysis-topic/ee-ac-analysis/v/ee-complex-numbers |
| 258 | +[ints]: https://docs.python.org/3/library/functions.html#int |
| 259 | +[floats]: https://docs.python.org/3/library/functions.html#float |
2 | 260 |
|
0 commit comments