Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complex-numbers concept docs #3554

Merged
merged 42 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
eda3a5a
complex-numbers concept docs
colinleach Nov 25, 2023
8165d51
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
6fe58da
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
17d8b42
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
b0a6f94
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
9e23c2c
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
498c565
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
ca8f941
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
2f568e5
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
a51f39f
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
e2fca12
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
77f574c
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
c6ec6a6
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
2e0f35e
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
d84f687
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
934d33c
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
5653132
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
759bb5b
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
ef8ab6e
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
b4b02ab
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
153c019
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
72fabca
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
38d37f8
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
bf81d3a
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
c8b8fc1
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
f8ac3cd
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
efd391b
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
1e59be5
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
67d0653
Update concepts/complex-numbers/about.md
colinleach Nov 27, 2023
93b26d8
fixed several links
colinleach Nov 27, 2023
5b1dcf3
some relatively small fixes, mainly typos and formatting
colinleach Nov 28, 2023
b674997
Moved sections around, in the search for a clearer flow of ideas.
colinleach Nov 28, 2023
02867e1
added bit on `complex(string)` constructor.
colinleach Nov 28, 2023
8942925
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
0dcf403
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
6e12c30
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
d773536
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
7113623
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
4dfc09d
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
a2aa792
Update concepts/complex-numbers/about.md
colinleach Nov 29, 2023
f648017
Edited About to serve as Introduction
BethanyG Dec 5, 2023
86d4093
Titled Introduction as Introduction
BethanyG Dec 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions concepts/complex-numbers/.meta/config.json
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": []
}
182 changes: 181 additions & 1 deletion concepts/complex-numbers/about.md
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.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
They are so useful, especially in engineering and science, that Python includes [`complex`][complex] as a standard type alongside integers and floating-point numbers.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
## 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.
BethanyG marked this conversation as resolved.
Show resolved Hide resolved
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:
colinleach marked this conversation as resolved.
Show resolved Hide resolved

colinleach marked this conversation as resolved.
Show resolved Hide resolved
```python
>>> z1 = complex(1.5, 2.0)
>>> z1
(1.5+2j)
```

Most engineers are happy with `j`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add how to declare a complex number literal here in this section. I like the info you list below, but worry that the "break" might have students "losing the thread".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go away and think about this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to address this as part of b674997.

That changes the document quite a bit, so I'll be particularly interested in your comments.

Most scientists and mathematicians prefer `i`, but in designing Python the engineers won.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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`.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs talk about using 0j, which is the default in the constructor if you omit an imaginary part. Why one would do that is a mystery ... but there you have it.

..and as I think about this, we may want to show both complex('0+1j') and complex('1+0j'), just to hammer home that a complex type remains complex, even if its imaginary part is set to zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this towards the end of the introduction.

```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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't decided yet if we need more info around this. We may want this piece up toward the intro, as a way of showing what a complex number "looks like" in Python.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another part of b674997.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
>>> z2.real
2.0
>>> z2.imag
1.5
```

## Arithmetic

Most of the [`operators`][operators] used with floats also work with complex

colinleach marked this conversation as resolved.
Show resolved Hide resolved
```python
>>> z1, z2
((1.5+2j), (2+1.5j))

colinleach marked this conversation as resolved.
Show resolved Hide resolved
>>> 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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to omit this aside, or pull out the explanation of j into the text. I know folx really don't have to think about this -- that's the whole point of using i or j -- but this would be the first time a student encounters the definition of j in the text, and its not very prominent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I worried about after I submitted the PR, so something needs changing. More thought...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at the intro now and see what you think of the changes.

```

Explaining the rules for complex multiplication and division is out of scope here.
Any introduction to complex numbers will cover this.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Alternatively, Exercism has a `Complex Numbers` practice exercise where you can implement this from first principles.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

colinleach marked this conversation as resolved.
Show resolved Hide resolved
Integer division is ___not___ possible on complex numbers, so the `//` and `%` operators and `divmod()` function will fail.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
There are two functions that are useful with complex numbers:
- `conjugate()` simply flips the sign of the complex part.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
Because of the way complex multiplication works, this is more useful than you might think.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
- `abs()` is guaranteed to return a real number with no imaginary part.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
```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.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

colinleach marked this conversation as resolved.
Show resolved Hide resolved
Details are available in the [`cmath`][cmath] module documents, but the main categories are:
- conversion between Cartesian and polar coordinates
colinleach marked this conversation as resolved.
Show resolved Hide resolved
- exponential and log functions
- trig functions
- hyperbolic functions
- classification functions
- useful constants

colinleach marked this conversation as resolved.
Show resolved Hide resolved
```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.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Complex exponentials are ___much___ easier to work with.
Complex exponentials are ___much___ easier to work with, and moving these waves to a representation on the complex number plane simplifies calculations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't mention the complex plane before, and I had already wondered if we should. I resisted the temptation to include a graphic showing the complex plane and unit circle, and magnitude vs phase. Maybe a Wikipedia link?

Too much of this and we'll be discussing the Cauchy-Riemann equations and having to explain partial differential equations...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure what to do about this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me either. All of the examples I've found have shown the unit circle and how things translate (rotate) when put on the complex plane. this rundown from Real Python uses a (contrived) example of the Bermuda Triangle. Very tempted to adapt it with a different region of the globe. Or maybe we use a simple geometric form and how it can be flipped and rotated easier on the complex plane. URG. More thought needed on my part, clearly.

### But I never use complex numbers!

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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.

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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__.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
- 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.
colinleach marked this conversation as resolved.
Show resolved Hide resolved
- Also, it is in the digital filters that let a cellphone mast separate your signal from everyone else's.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

colinleach marked this conversation as resolved.
Show resolved Hide resolved
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.
colinleach marked this conversation as resolved.
Show resolved Hide resolved

colinleach marked this conversation as resolved.
Show resolved Hide resolved
[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
130 changes: 129 additions & 1 deletion concepts/complex-numbers/introduction.md
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
16 changes: 6 additions & 10 deletions concepts/complex-numbers/links.json
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."
}
]
Loading