-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1cd88ed
commit eda3a5a
Showing
4 changed files
with
318 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"blurb": "TODO: add blurb for this concept", | ||
"authors": ["bethanyg", "cmccandless"], | ||
"blurb": "Complex numbers are a fundamental data type in Python, along with int and float. Further support is added with the cmath module, which is part of the Python standard library.", | ||
"authors": ["bethanyg", "cmccandless", "colinleach"], | ||
"contributors": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,182 @@ | ||
#TODO: Add about for this concept. | ||
# About | ||
|
||
`Complex numbers` are not complicated. | ||
They just need a less alarming name. | ||
|
||
They are so useful, especially in engineering and science, that Python includes [`complex`][complex] as a standard type alongside integers and floating-point numbers. | ||
|
||
## Basics | ||
|
||
A `complex` value in Python is essentially a pair of floating-point numbers. | ||
These are called the "real" and "imaginary" parts, for unfortunate historical reasons. | ||
Again, it is best to focus on the underlying simplicity and not the strange names. | ||
|
||
There are two common ways to create them. | ||
The `complex(real, imag)` constructor takes two `float` parameters: | ||
|
||
```python | ||
>>> z1 = complex(1.5, 2.0) | ||
>>> z1 | ||
(1.5+2j) | ||
``` | ||
|
||
Most engineers are happy with `j`. | ||
Most scientists and mathematicians prefer `i`, but in designing Python the engineers won. | ||
|
||
So there are two rules for an imaginary part: | ||
- It is designated with `j` not `i`. | ||
- The `j` must immediately follow a number, to prevent Python seeing it as a variable name. If necessary, use `1j`. | ||
|
||
```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'> | ||
``` | ||
|
||
With this, we have a second and perhaps clearer way to create a complex number: | ||
```python | ||
>>> z2 = 2.0 + 1.5j | ||
>>> z2 | ||
(2+1.5j) | ||
``` | ||
The end result is identical to using a constructor. | ||
|
||
To access the parts individually: | ||
```python | ||
>>> z2.real | ||
2.0 | ||
>>> z2.imag | ||
1.5 | ||
``` | ||
|
||
## Arithmetic | ||
|
||
Most of the [`operators`][operators] used with floats also work with complex | ||
|
||
```python | ||
>>> z1, z2 | ||
((1.5+2j), (2+1.5j)) | ||
|
||
>>> z1 + z2 # addition | ||
(3.5+3.5j) | ||
|
||
>>> z1 - z2 # subtraction | ||
(-0.5+0.5j) | ||
|
||
>>> z1 * z2 # multiplication | ||
6.25j | ||
|
||
>>> z1 / z2 # division | ||
(0.96+0.28j) | ||
|
||
>>> z1 ** 2 # exponentiation | ||
(-1.75+6j) | ||
|
||
>>> 2 ** z1 # another exponentiation | ||
(0.5188946835878313+2.7804223253571183j) | ||
|
||
>>> 1j ** 2 # j is the square root of -1 | ||
(-1+0j) | ||
``` | ||
|
||
Explaining the rules for complex multiplication and division is out of scope here. | ||
Any introduction to complex numbers will cover this. | ||
Alternatively, Exercism has a `Complex Numbers` practice exercise where you can implement this from first principles. | ||
|
||
Integer division is ___not___ possible on complex numbers, so the `//` and `%` operators and `divmod()` function will fail. | ||
|
||
There are two functions that are useful with complex numbers: | ||
- `conjugate()` simply flips the sign of the complex part. | ||
Because of the way complex multiplication works, this is more useful than you might think. | ||
- `abs()` is guaranteed to return a real number with no imaginary part. | ||
|
||
```python | ||
>>> z1 | ||
(1.5+2j) | ||
|
||
>>> z1.conjugate() # flip the z1.imag sign | ||
(1.5-2j) | ||
|
||
>>> abs(z1) # sqrt(z1.real ** 2 + z1.imag ** 2) | ||
2.5 | ||
``` | ||
|
||
## The `cmath` module | ||
|
||
The Python standard library has a `math` module full of useful functionality for working with real numbers. | ||
It also has an equivalent `cmath` module for complex numbers. | ||
|
||
Details are available in the [`cmath`][cmath] module documents, but the main categories are: | ||
- conversion between Cartesian and polar coordinates | ||
- exponential and log functions | ||
- trig functions | ||
- hyperbolic functions | ||
- classification functions | ||
- useful constants | ||
|
||
```python | ||
>>> import cmath | ||
|
||
>>> euler = cmath.exp(1j * cmath.pi) # Euler's equation | ||
|
||
>>> euler.real | ||
-1.0 | ||
>>> round(euler.imag, 15) # round to 15 decimal places | ||
0.0 | ||
``` | ||
|
||
So a simple expression with three of the most important constants in nature `e`, `i` (or `j`) and `pi` gives the result `-1`. | ||
Some people believe this is the most beautiful result in all of mathematics. | ||
It dates back to around 1740. | ||
|
||
----- | ||
|
||
## Optional section: a Complex Numbers FAQ | ||
|
||
This part can be skipped, unless you are interested. | ||
|
||
### Isn't this some strange new piece of pure mathematics? | ||
|
||
It was strange and new in the 16th century. | ||
|
||
500 years later, it is central to most of engineering and the physical sciences. | ||
|
||
### Why would anyone use these? | ||
|
||
It turns out that complex numbers are the simplest way to describe anything that rotates or anything with a wave-like property. | ||
|
||
You can see things rotate. | ||
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. | ||
|
||
Less obviously, sound is wave-like, light is wave-like, radio signals are wave-like, The economy of your home country is at least partly wave-like. | ||
|
||
A lot of this can be done with trig functions (`sin()` and `cos()`) but that gets messy quickly. | ||
Complex exponentials are ___much___ easier to work with. | ||
|
||
### But I never use complex numbers! | ||
|
||
Only true if you are living in a cave and foraging for your food. | ||
|
||
If you read this on any sort of screen, you are utterly dependent on some useful 20th-centry advances. | ||
|
||
1. __Semiconductor chips__. | ||
- These make no sense in classical physics and can only be explained (and designed) by quantum mechanics (QM). | ||
- In QM, everything is complex-valued by definition. | ||
2. __The Fast Fourier Transform algorithm__. | ||
- FFT is an application of complex numbers, and it is in everything. | ||
- Audio files? MP3 and other formats use FFT for compression. So does MP4 video, JPEG photos, among many others. | ||
- Also, it is in the digital filters that let a cellphone mast separate your signal from everyone else's. | ||
|
||
So, you are probably using complex numbers thousands of times per second. | ||
Be grateful to the tech people who understand this stuff so that you maybe don't need to. | ||
|
||
[complex]: https://docs.python.org/3/library/functions.html#complex | ||
[cmath]: https://docs.python.org/3/library/cmath.html | ||
[operators]: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,130 @@ | ||
#TODO: Add introduction for this concept. | ||
# Introduction | ||
|
||
`Complex numbers` are not complicated. | ||
They just need a less alarming name. | ||
|
||
They are so useful, especially in engineering and science, that Python includes [`complex`][complex] as a standard type alongside integers and floating-point numbers. | ||
|
||
## Basics | ||
|
||
A `complex` value in Python is essentially a pair of floating-point numbers. | ||
These are called the "real" and "imaginary" parts. | ||
|
||
There are two common ways to create them. | ||
The `complex(real, imag)` constructor takes two `float` parameters: | ||
|
||
```python | ||
>>> z1 = complex(1.5, 2.0) | ||
>>> z1 | ||
(1.5+2j) | ||
``` | ||
|
||
There are two rules for an imaginary part: | ||
- It is designated with `j` (not `i`, which you may see in textbooks). | ||
- The `j` must immediately follow a number, to prevent Python seeing it as a variable name. If necessary, use `1j`. | ||
|
||
```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'> | ||
``` | ||
|
||
With this, we have a second way to create a complex number: | ||
```python | ||
>>> z2 = 2.0 + 1.5j | ||
>>> z2 | ||
(2+1.5j) | ||
``` | ||
The end result is identical to using a constructor. | ||
|
||
To access the parts individually: | ||
```python | ||
>>> z2.real | ||
2.0 | ||
>>> z2.imag | ||
1.5 | ||
``` | ||
|
||
## Arithmetic | ||
|
||
Most of the [`operators`][operators] used with `float` also work with `complex`: | ||
|
||
```python | ||
>>> z1, z2 | ||
((1.5+2j), (2+1.5j)) | ||
|
||
>>> z1 + z2 # addition | ||
(3.5+3.5j) | ||
|
||
>>> z1 - z2 # subtraction | ||
(-0.5+0.5j) | ||
|
||
>>> z1 * z2 # multiplication | ||
6.25j | ||
|
||
>>> z1 / z2 # division | ||
(0.96+0.28j) | ||
|
||
>>> z1 ** 2 # exponentiation | ||
(-1.75+6j) | ||
|
||
>>> 2 ** z1 # another exponentiation | ||
(0.5188946835878313+2.7804223253571183j) | ||
|
||
>>> 1j ** 2 # j is the square root of -1 | ||
(-1+0j) | ||
``` | ||
|
||
Explaining the rules for complex multiplication and division is out of scope here. | ||
Any introduction to complex numbers will cover this. | ||
Alternatively, Exercism has a `Complex Numbers` practice exercise where you can implement this from first principles. | ||
|
||
There are two functions that are useful with complex numbers: | ||
- `conjugate()` simply flips the sign of the complex part. | ||
- `abs()` is guaranteed to return a real number with no imaginary part. | ||
|
||
```python | ||
>>> z1 | ||
(1.5+2j) | ||
|
||
>>> z1.conjugate() # flip the z1.imag sign | ||
(1.5-2j) | ||
|
||
>>> abs(z1) # sqrt(z1.real ** 2 + z1.imag ** 2) | ||
2.5 | ||
``` | ||
|
||
## The `cmath` module | ||
|
||
The Python standard library has a `math` module full of useful functionality for working with real numbers. | ||
It also has an equivalent `cmath` module for complex numbers. | ||
|
||
Details are available in the [`cmath`][cmath] module documents, but the main categories are: | ||
- conversion between Cartesian and polar coordinates | ||
- exponential and log functions | ||
- trig functions | ||
- hyperbolic functions | ||
- classification functions | ||
- useful constants | ||
|
||
```python | ||
>>> import cmath | ||
|
||
>>> euler = cmath.exp(1j * cmath.pi) # Euler's equation | ||
|
||
>>> euler.real | ||
-1.0 | ||
>>> round(euler.imag, 15) # round to 15 decimal places | ||
0.0 | ||
``` | ||
|
||
[complex]: https://docs.python.org/3/library/functions.html#complex | ||
[cmath]: https://docs.python.org/3/library/cmath.html | ||
[operators]: https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,14 @@ | ||
[ | ||
{ | ||
"url": "http://example.com/", | ||
"description": "TODO: add new link (above) and write a short description here of the resource." | ||
"url": "https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex/", | ||
"description": "Operations on numeric types." | ||
}, | ||
{ | ||
"url": "http://example.com/", | ||
"description": "TODO: add new link (above) and write a short description here of the resource." | ||
"url": "https://docs.python.org/3/library/functions.html#complex/", | ||
"description": "The complex class." | ||
}, | ||
{ | ||
"url": "http://example.com/", | ||
"description": "TODO: add new link (above) and write a short description here of the resource." | ||
}, | ||
{ | ||
"url": "http://example.com/", | ||
"description": "TODO: add new link (above) and write a short description here of the resource." | ||
"url": "https://docs.python.org/3/library/cmath.html/", | ||
"description": "Module documentation for cmath." | ||
} | ||
] |