|
| 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 Julia includes [complex numbers][complex] as standard numeric types alongside integers and floating-point numbers. |
| 7 | + |
| 8 | +## Basics |
| 9 | + |
| 10 | +A `complex` value in Julia is essentially a pair of numbers: usually but not always floating-point. |
| 11 | +These are called the "real" and "imaginary" parts, for unfortunate historical reasons. |
| 12 | +Again, it is best to focus on the underlying simplicity and not the strange names. |
| 13 | + |
| 14 | +To create complex numbers from two real numbers, just add the suffix `im` to the imaginary part. |
| 15 | + |
| 16 | +```julia-repl |
| 17 | +julia> z = 1.2 + 3.4im |
| 18 | +1.2 + 3.4im |
| 19 | +
|
| 20 | +julia> typeof(z) |
| 21 | +ComplexF64 (alias for Complex{Float64}) |
| 22 | +
|
| 23 | +julia> zi = 1 + 2im |
| 24 | +1 + 2im |
| 25 | +
|
| 26 | +julia> typeof(zi) |
| 27 | +Complex{Int64} |
| 28 | +``` |
| 29 | + |
| 30 | +Thus there are various `Complex` types, derived from the corresponding integer or floating-point type. |
| 31 | + |
| 32 | +To create a complex number from real variables, the above syntax will not work. |
| 33 | +Writing `a + bim` confuses the parser into thinking `bim` is a (non-existent) variable name. |
| 34 | + |
| 35 | +Writing `b*im` is possible, but the preferred method uses the `complex()` function. |
| 36 | + |
| 37 | +```julia-repl |
| 38 | +julia> a = 1.2; b = 3.4; complex(a, b) |
| 39 | +1.2 + 3.4im |
| 40 | +``` |
| 41 | + |
| 42 | +You may wonder, why `im` rather than `i` or `j`? |
| 43 | + |
| 44 | +Most engineers are happy with `j`. |
| 45 | +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. |
| 46 | + |
| 47 | +The [manual][complex] states that "Using mathematicians' i or engineers' j for this global constant was rejected since they are such popular index variable names". |
| 48 | + |
| 49 | +By happy coincidence, this also avoids long arguments between engineers and everyone else. |
| 50 | +Feel free to form your own judgement about whether this influenced the decision. |
| 51 | + |
| 52 | +To access the parts of a complex number individually: |
| 53 | + |
| 54 | +```julia-repl |
| 55 | +julia> z = 1.2 + 3.4im |
| 56 | +1.2 + 3.4im |
| 57 | +
|
| 58 | +julia> real(z) |
| 59 | +1.2 |
| 60 | +
|
| 61 | +julia> imag(z) |
| 62 | +3.4 |
| 63 | +``` |
| 64 | + |
| 65 | +Either part can be zero and mathematicians may then talk of the number being "wholly real" or "wholly imaginary". |
| 66 | +However, it is still a complex number in Julia. |
| 67 | + |
| 68 | +```julia-repl |
| 69 | +julia> zr = 1.2 + 0im |
| 70 | +1.2 + 0.0im |
| 71 | +
|
| 72 | +julia> typeof(zr) |
| 73 | +ComplexF64 (alias for Complex{Float64}) |
| 74 | +
|
| 75 | +julia> zi = 3.4im |
| 76 | +0.0 + 3.4im |
| 77 | +
|
| 78 | +julia> typeof(zi) |
| 79 | +ComplexF64 (alias for Complex{Float64}) |
| 80 | +``` |
| 81 | + |
| 82 | +You may have heard that "`i` (or `j`) is the square root of -1". |
| 83 | + |
| 84 | +For now, all this means is that the imaginary part _by definition_ satisfies the following equality: |
| 85 | + |
| 86 | +```julia-repl |
| 87 | +julia> 1im * 1im == -1 |
| 88 | +true |
| 89 | +``` |
| 90 | + |
| 91 | +This is a simple idea, but it leads to interesting consequences. |
| 92 | + |
| 93 | +## Arithmetic |
| 94 | + |
| 95 | +Most of the [`operators`][operators] used with floats and integers also work with complex numbers: |
| 96 | + |
| 97 | +```julia-repl |
| 98 | +julia> z1 = 1.5 + 2im |
| 99 | +1.5 + 2.0im |
| 100 | +
|
| 101 | +julia> z2 = 2 + 1.5im |
| 102 | +2.0 + 1.5im |
| 103 | +
|
| 104 | +julia> z1 + z2 # addition |
| 105 | +3.5 + 3.5im |
| 106 | +
|
| 107 | +julia> z1 * z2 # multiplication |
| 108 | +0.0 + 6.25im |
| 109 | +
|
| 110 | +julia> z1 / z2 # division |
| 111 | +0.96 + 0.28im |
| 112 | +
|
| 113 | +julia> z1^2 # exponentiation |
| 114 | +-1.75 + 6.0im |
| 115 | +
|
| 116 | +julia> 2^z1 # another exponentiation |
| 117 | +0.5188946835878313 + 2.7804223253571183im |
| 118 | +``` |
| 119 | + |
| 120 | +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_). |
| 121 | + |
| 122 | +Any [mathematical][math-complex] or [electrical engineering][engineering-complex] introduction to complex numbers will cover this, should you want to dig into the topic. |
| 123 | + |
| 124 | +Alternatively, Exercism has a `Complex Numbers` practice exercise where you can implement a complex number class with these operations from first principles. |
| 125 | + |
| 126 | +Integer division is (mostly) ___not___ possible on complex numbers, so the `//`, `÷` and `%` operators will fail for the complex number type. |
| 127 | +An exception is using `//` with complex _integers_ to get complex rational numbers, but this is probably not often useful. |
| 128 | + |
| 129 | +## Functions |
| 130 | + |
| 131 | +Most mathematical functions will work with complex inputs. |
| 132 | + |
| 133 | +However, providing real inputs and expecting a complex output will not usually work. |
| 134 | +This is a performance optimization that should make more sense after looking at the Multiple Dispatch concept. |
| 135 | + |
| 136 | +```julia-repl |
| 137 | +julia> sin(1.5 + 2.0im) |
| 138 | +3.752771340479298 + 0.25655395609048176im |
| 139 | +
|
| 140 | +julia> sqrt(-1) |
| 141 | +ERROR: DomainError with -1.0: |
| 142 | +sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)). |
| 143 | +
|
| 144 | +julia> sqrt(-1 + 0im) |
| 145 | +0.0 + 1.0im |
| 146 | +``` |
| 147 | + |
| 148 | +There are several functions, in addition to `real()` and `imag()`, with particular relevance for complex numbers. |
| 149 | +Please skip over these if they make no sense to you! |
| 150 | + |
| 151 | +- `conj()` 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 | +- `abs2(<complex number>)` returns the square of `abs(<complex number>)`: quicker to calculate than `abs()`, and often what a calculation needs. |
| 155 | +- `angle(<complex number>)` returns the phase angle in radians. |
| 156 | + |
| 157 | +```julia-repl |
| 158 | +julia> z1 |
| 159 | +1.5 + 2.0im |
| 160 | +
|
| 161 | +julia> conj(z1) |
| 162 | +1.5 - 2.0im |
| 163 | +
|
| 164 | +julia> abs(z1) |
| 165 | +2.5 |
| 166 | +
|
| 167 | +julia> abs2(z1) |
| 168 | +6.25 |
| 169 | +
|
| 170 | +julia> angle(z1) |
| 171 | +0.9272952180016122 |
| 172 | +``` |
| 173 | +A partial explanation, for the mathematically-minded _(again, feel free to skip)_: |
| 174 | + |
| 175 | +- The `(real, imag)` representation of `z1` in effect uses Cartesian coordinates on the complex plane. |
| 176 | +- The same complex number can be represented in `(r, θ)` notation, using polar coordinates. |
| 177 | +- Here, `r` and `θ` are given by `abs(z1)` and `angle(z1)` respectively. |
| 178 | + |
| 179 | + |
| 180 | + |
| 181 | +Here is an example using some constants: |
| 182 | + |
| 183 | +```julia-repl |
| 184 | +julia> euler = exp(1im * π) |
| 185 | +-1.0 + 1.2246467991473532e-16im |
| 186 | +
|
| 187 | +julia> real(euler) |
| 188 | +-1.0 |
| 189 | +
|
| 190 | +julia> round(imag(euler), digits=15) # round to 15 decimal places |
| 191 | +0.0 |
| 192 | +``` |
| 193 | + |
| 194 | +So a simple expression with three of the most important constants in nature `e`, `i` (or `j`) and `pi` gives the result `-1`. |
| 195 | +Some people believe this is the most beautiful result in all of mathematics. |
| 196 | +It dates back to around 1740. |
| 197 | + |
| 198 | +----- |
| 199 | + |
| 200 | +## Optional section: a Complex Numbers FAQ |
| 201 | + |
| 202 | +This part can be skipped, unless you are interested. |
| 203 | + |
| 204 | +### Isn't this some strange new piece of pure mathematics? |
| 205 | + |
| 206 | +It was strange and new in the 16th century. |
| 207 | + |
| 208 | +500 years later, it is central to most of engineering and the physical sciences. |
| 209 | + |
| 210 | +### Why would anyone use these? |
| 211 | + |
| 212 | +It turns out that complex numbers are the simplest way to describe anything that rotates or anything with a wave-like property. |
| 213 | +So they are used widely in electrical engineering, audio processing, physics, computer gaming, and navigation - to name only a few applications. |
| 214 | + |
| 215 | +You can see things rotate. |
| 216 | +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. |
| 217 | + |
| 218 | +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. |
| 219 | + |
| 220 | +A lot of this wave processing can be done with trig functions (`sin()` and `cos()`) but that gets messy quite quickly. |
| 221 | + |
| 222 | +Complex exponentials are ___much___ easier to work with. |
| 223 | + |
| 224 | +### But I don't need complex numbers! |
| 225 | + |
| 226 | +Only true if you are living in a cave and foraging for your food. |
| 227 | + |
| 228 | +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. |
| 229 | + |
| 230 | +1. __Semiconductor chips__. |
| 231 | + - These make no sense in classical physics and can only be explained (and designed) by quantum mechanics (QM). |
| 232 | + - In QM, everything is complex-valued by definition. (_it's waveforms all the way down_) |
| 233 | + |
| 234 | +2. __The Fast Fourier Transform algorithm__. |
| 235 | + - FFT is an application of complex numbers, and it is in _everything_ connected to sound transmission, audio processing, photos, and video. |
| 236 | + |
| 237 | + - MP3 and other audio formats use FFT for compression, ensuring more audio can fit within a smaller storage space. |
| 238 | + - JPEG compression and MP4 video, among many other image and video formats, also use FFT for compression. |
| 239 | + |
| 240 | + - FFT is also deployed in the digital filters that allow cellphone towers to separate your personal cell signal from everyone else's. |
| 241 | + |
| 242 | +So, you are probably using technology that relies on complex number calculations thousands of times per second. |
| 243 | + |
| 244 | + |
| 245 | +[complex]: https://docs.julialang.org/en/v1/manual/complex-and-rational-numbers/#Complex-Numbers |
| 246 | +[math-complex]: https://www.nagwa.com/en/videos/143121736364/ |
| 247 | +[engineering-complex]: https://www.khanacademy.org/science/electrical-engineering/ee-circuit-analysis-topic/ee-ac-analysis/v/ee-complex-numbers |
| 248 | +[operators]: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex |
0 commit comments