Skip to content

Commit a0cba48

Browse files
ClémentClément
authored andcommitted
Improving explanations for change of base.
1 parent bb72ce5 commit a0cba48

File tree

1 file changed

+36
-20
lines changed

1 file changed

+36
-20
lines changed

source/docs/programming_and_computer_usage/complexity.md

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,18 @@ This growth rate is classified according to ["orders"](https://en.wikipedia.org/
2323

2424
Using $|\cdot|$ to denote the absolute value, we write:
2525

26-
$$f(x) = O(g(x))$$
26+
$$f(n) = O(g(n))$$
2727

28-
if there exists positive numbers $n$ and $x_0$ such that
28+
if there exists positive numbers $m$ and $k$ such that
2929

30-
$$|f(x)| \leqslant M |g(x)|$$
30+
$$|f(n)| \leqslant m \times |g(n)|$$
3131

32-
for all $x \geqslant x_0$.
32+
for all $n \geqslant k$.
33+
34+
Stated differently, the size of $f$'s output (which we will use to represent the time or space needed by $f$ to carry out its computation) can be bounded by the size of $g$'s output,
35+
36+
- up to a multiplicative factor ($m$) that does *not* depend of $n$ (it is fixed once and for all),
37+
- for inputs that are "large enough" (that is, greater than $k$, which again does not depend on $n$, it is fixed once and for all).
3338

3439
### Common orders of magnitude
3540

@@ -94,17 +99,19 @@ Our `while(true)` loop *will* terminate, since we are bound to produce a value o
9499

95100
[Download the project](./code/projects/GrowthMagnitudes.zip) to see how fast other magnitude produce a value exceeding `int`'s capacity, and do not hesitate to edit this code to have all input values starting at 0 to "feel" the difference it makes in terms of time!
96101

97-
# The Example of Integers
102+
## The Example of Integers
98103

99-
## Abstraction and Representation
104+
### Abstraction and Representation
100105

101106
To measure the time and space consumption of programs, we make some simplifying assumptions:
102107

103108
- Hardware is discarded: we compare programs assuming they run on the same platform, and do *not* consider if a program would be "better" on parallel hardware.
104109
- Constants are discarded: if a program is twice as slow as another one, we still consider them to be in the same order of magnitude^[This is captured by the "constant factor" property of the big O notation.].
105110
- *Representations* are in general discarded, as programs are assumed to use the same: for example, if the implementation of the `int` datatype is "reasonable" and the same for all programs, then we can discard it.
106111

107-
## How integers are represented
112+
How "reasonable" is defined is tricky, and we discuss it in the next section.
113+
114+
### How integers are represented
108115

109116
Compare the following three ways of representing integers:
110117

@@ -114,32 +121,41 @@ Unary (Tallies) | 1 | III, IIIIIII, IIIIIIII, … | $O(n)$ |
114121
Binary | 2 | 01011, 10011101, 101101010, … | $O(\log_2(n))$ |
115122
Decimal | 10 | 123, 930, 120,439, … | $O(\log_{10}(n))$ |
116123

117-
Actually, it takes roughly [$\log_2(n) / \log_2(b)$ digits](https://math.stackexchange.com/a/4490764) to represent the number $n$ in base $b$, except if $b = 1$.
124+
It takes roughly [$\log_2(n) / \log_2(b)$ digits](https://math.stackexchange.com/a/4490764) to represent the number $n$ in base $b$, except if $b = 1$.
118125

119126
And indeed we can confirm that for $b = 10$, we have
120127

121128
$$\log_2(n) / \log_2(b) = \log_{10}(n)$$
122129

123130
by [changing the base](https://en.wikipedia.org/wiki/List_of_logarithmic_identities#Changing_the_base) of the logarithm.
124131

125-
## Why it (almost) does not matter
132+
### Why it (almost) does not matter
133+
134+
Now, imagine that we have a program manipulating integers in base $b$, and we want to convert them in base $b'$.
135+
We will ignore [how much time](https://cs.stackexchange.com/a/21799) is required to perform this conversion, and simply focus on the memory gain or loss.
136+
137+
Base | Size of $n$ |
138+
--- | ------------ |
139+
Base $b$ | $\log_2(n) \ \log_2(b)$ |
140+
Base $b'$ | $\log_2(n) \ \log_2(b')$ |
141+
142+
Hence, converting a number $n$ in base $b$ into a number in base $b'$ results in a number that uses $\log_{2}(b) / \log_{2}(b')$ more (or less!) space.
143+
Notice, and this is very important, that is expression *does not depend on $n$, but only on $b$ and $b'$*, hence the "constant factor" property of the big O notation tells us that we do not care about such a change.
126144

127-
Now, imagine that we have a program manipulating integers in base $b$.
128-
Converting numbers in base $b'$ result in numbers that use $\log_2(b') / \log_2(b)$ more (or less!) space.
129-
For example, going from base $10$ to base $2$ means that $b = 2$ and $b' = 10$, hence we need $\log_2(10) / \log_2(2) = 3.322 / 1$ times more space to store and manipulate the integers.
145+
For example, going from base $10$ to base $2$ means that $b = 10$ and $b' = 2$, hence we need $\log_2(10) / \log_2(2) = 3.322 / 1$ times more space to store and manipulate the integers.
130146
This corresponds intuitively to 32 bits being able to store at most a 10-digit number (2,147,483,647).
131147

132-
If our program in base $b$ uses $O(g(n))$, it means that a program performing the same task, with the same algorithm, but using integers in base $b'$, would require $O((\log_2(b) / \log_2(b')) \times g(n))$.
148+
If our program in base $b$ uses memory of order $O(g(n))$, it means that a program performing the same task, with the same algorithm, but using integers in base $b'$, would have its memory usage bounded by $O((\log_2(b) / \log_2(b')) \times g(n))$.
133149
By adapting the constant factor principle of the big O notation, we can see that this is a negligible factor that can be omitted.
134150

135-
However, if the $b'$ base is 1, then the new program will use $O(n \times g(n))$: if $g(n)$ is greater than linear, this will make a difference!
136-
Of course, unary representation is "not" reasonable, so we will always assume that our representations are related by some constant, making the function order of magnitude insensible to such details.
151+
However, if the $b'$ base is 1, then the new program will use $O(n \times g(n))$: if $g(n)$ is greater than linear, this will make a difference^[This can already be seen by observing that $\log_{2}(b) / \log_{2}(b')$, if $b' = 1$, is impossible, since we cannot divide by $\log_2(1) =0$.]
152+
Of course, unary representation is *not* reasonable, so we will always assume that our representations are related by some constant, making the function order of magnitude insensible to such details.
137153

138154
You can have a look at [the complexity of various arithmetic functions](https://en.wikipedia.org/wiki/Computational_complexity_of_mathematical_operations#Arithmetic_functions) and see that the representation is not even discussed, as those results are insensible to them, provided they are "reasonable".
139155

140-
# Types of Bounds
156+
## Types of Bounds
141157

142-
## Foreword
158+
### Foreword
143159

144160
When considering order of magnitude, we are always *asymptotic*, i.e., we consider that the input will grow for ever.
145161
The Big-O notation above furthermore corresponds to the *worst case*, but two other cases are sometimes considered:
@@ -155,9 +171,9 @@ The reason why worst case is generally preferred is because:
155171
- Best case is considered unreliable as it can easily be tweaked, and may not be representative of the algorithm's resource consumption in general,
156172
- Average case is difficult to compute, and not necessarily useful, as worst and average complexity are often the same.
157173

158-
## Examples
174+
### Examples
159175

160-
### Linear search algorithm
176+
#### Linear search algorithm
161177

162178
The [linear search algorithm](https://princomp.github.io/lectures/data/search#finding-a-particular-value) look for a particular value in an array by inspecting the values one after the other:
163179

@@ -189,6 +205,6 @@ Similarly, considering that the array is of size $n$, and counting how many time
189205
Note that the space usage of both algorithms are $O(c)$, as they require only one variable if we do not copy the array.
190206
Note, also, that both algorithms have the same worst case and average case complexity, which are the cases we are actually interested in.
191207

192-
### Matrix Multiplication
208+
#### Matrix Multiplication
193209

194210
Consider the ["schoolbook algorithm for multiplication"](https://en.wikipedia.org/wiki/Computational_complexity_of_matrix_multiplication#Schoolbook_algorithm)

0 commit comments

Comments
 (0)