You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source/docs/programming_and_computer_usage/complexity.md
+36-20Lines changed: 36 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,13 +23,18 @@ This growth rate is classified according to ["orders"](https://en.wikipedia.org/
23
23
24
24
Using $|\cdot|$ to denote the absolute value, we write:
25
25
26
-
$$f(x) = O(g(x))$$
26
+
$$f(n) = O(g(n))$$
27
27
28
-
if there exists positive numbers $n$ and $x_0$ such that
28
+
if there exists positive numbers $m$ and $k$ such that
29
29
30
-
$$|f(x)| \leqslant M |g(x)|$$
30
+
$$|f(n)| \leqslant m \times |g(n)|$$
31
31
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).
33
38
34
39
### Common orders of magnitude
35
40
@@ -94,17 +99,19 @@ Our `while(true)` loop *will* terminate, since we are bound to produce a value o
94
99
95
100
[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!
96
101
97
-
# The Example of Integers
102
+
##The Example of Integers
98
103
99
-
## Abstraction and Representation
104
+
###Abstraction and Representation
100
105
101
106
To measure the time and space consumption of programs, we make some simplifying assumptions:
102
107
103
108
- 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.
104
109
- 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.].
105
110
-*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.
106
111
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
108
115
109
116
Compare the following three ways of representing integers:
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$.
118
125
119
126
And indeed we can confirm that for $b = 10$, we have
120
127
121
128
$$\log_2(n) / \log_2(b) = \log_{10}(n)$$
122
129
123
130
by [changing the base](https://en.wikipedia.org/wiki/List_of_logarithmic_identities#Changing_the_base) of the logarithm.
124
131
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.
126
144
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.
130
146
This corresponds intuitively to 32 bits being able to store at most a 10-digit number (2,147,483,647).
131
147
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))$.
133
149
By adapting the constant factor principle of the big O notation, we can see that this is a negligible factor that can be omitted.
134
150
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.
137
153
138
154
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".
139
155
140
-
# Types of Bounds
156
+
##Types of Bounds
141
157
142
-
## Foreword
158
+
###Foreword
143
159
144
160
When considering order of magnitude, we are always *asymptotic*, i.e., we consider that the input will grow for ever.
145
161
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:
155
171
- Best case is considered unreliable as it can easily be tweaked, and may not be representative of the algorithm's resource consumption in general,
156
172
- Average case is difficult to compute, and not necessarily useful, as worst and average complexity are often the same.
157
173
158
-
## Examples
174
+
###Examples
159
175
160
-
### Linear search algorithm
176
+
####Linear search algorithm
161
177
162
178
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:
163
179
@@ -189,6 +205,6 @@ Similarly, considering that the array is of size $n$, and counting how many time
189
205
Note that the space usage of both algorithms are $O(c)$, as they require only one variable if we do not copy the array.
190
206
Note, also, that both algorithms have the same worst case and average case complexity, which are the cases we are actually interested in.
191
207
192
-
### Matrix Multiplication
208
+
####Matrix Multiplication
193
209
194
210
Consider the ["schoolbook algorithm for multiplication"](https://en.wikipedia.org/wiki/Computational_complexity_of_matrix_multiplication#Schoolbook_algorithm)
0 commit comments