m (→Crash Course in Scientific Computing) |
m |
||
Line 23: | Line 23: | ||
Then, from a terminal, <tt>jupyter-notebook</tt> opens a session in a browser, in which one can start a Julia session with a <tt>New</tt> invocation (and choosing julia there). | Then, from a terminal, <tt>jupyter-notebook</tt> opens a session in a browser, in which one can start a Julia session with a <tt>New</tt> invocation (and choosing julia there). | ||
− | + | There are some conventions in computer programming which become natural as you get used to them. For instance, $x=3$ takes a different meaning in most languages than in Mathematics. In the latter case, it means that the variable $x$ has the same value as the number 3. For a computer <tt>x=3</tt> assigns the value 3 to the variable x. In Julia that becomes: | |
− | < | + | <pre> |
− | + | julia> x=3 | |
− | </ | + | 3 |
+ | </pre> | ||
− | + | The output 3 is the result of our line of code, which reads: ''assigns the value 3 to x.'' The result of this is 3. In maths, if $x=3$, then $x\neq 4$, while in computer code, following <tt>x=3</tt>, we can have <tt>x=4</tt> meaning we now assign the value 4 to <tt>x</tt>. The computer code equivalent of the mathematical $=$ is actually <tt>==</tt>. Indeed: | |
− | < | + | <pre> |
− | + | julia> x=4 | |
− | + | 4 | |
− | + | julia> x==3 | |
+ | false | ||
+ | </pre> | ||
− | < | + | A typical line of code is to increment the value of a variable, which in many cases we would refer to as a counter: |
− | + | ||
− | </ | + | <pre> |
+ | x=x+1 | ||
+ | </pre> | ||
+ | |||
+ | Note that in Maths, this equality is trivially wrong. In computer code, on the other hand, it is so useful that we even have a special notation for it: | ||
+ | |||
+ | <pre> | ||
+ | x+=1 | ||
+ | </pre> | ||
+ | |||
+ | Incrementing the value of x and storing the result: | ||
+ | |||
+ | <pre> | ||
+ | julia> x=4 | ||
+ | 4 | ||
+ | |||
+ | julia> x+=1 | ||
+ | 5 | ||
+ | </pre> | ||
+ | |||
+ | A very early computer language which defined much of the conventions, notations and overall syntax of computer programming is [[C]]. An improved (and modernized) version implementing object-programming is known as C++, implying the joke it's an added version of C. | ||
+ | |||
+ | Most conventions are natural or familiar already | ||
+ | |||
+ | <pre> | ||
+ | julia> 3>2 | ||
+ | true | ||
+ | |||
+ | julia> 17<=5 | ||
+ | false | ||
+ | |||
+ | julia> 1+5!=2+3 | ||
+ | true | ||
+ | </pre> | ||
+ | |||
+ | but some others, we're not even sure we really want them: | ||
+ | |||
+ | <pre> | ||
+ | julia> 7/2==2\7 | ||
+ | true | ||
+ | </pre> | ||
+ | |||
+ | (this is called inverse division). More useful is the remainder $r$ from Euclidean division $a=bq+r$ which is obtained as <tt>a%b</tt>, for instance, $17=3\times 5+2$ so | ||
+ | |||
+ | <pre> | ||
+ | julia> 17%5 | ||
+ | 2 | ||
+ | |||
+ | julia> 17%3 | ||
+ | 2 | ||
+ | </pre> | ||
+ | |||
+ | so for instance, when we found that it was taking 205s for the computer of a dumb programmer to compute a Fibonacci number, we could give a better idea of the poor performance by giving the time in minutes: | ||
+ | |||
+ | <pre> | ||
+ | julia> floor(204/60) | ||
+ | 3.0 | ||
+ | |||
+ | julia> 204%60 | ||
+ | 25 | ||
+ | </pre> | ||
+ | |||
+ | where we used <tt>floor</tt> to extract the integer part (to lowest value; we'd use <tt>ceil</tt> for the highest value and <tt>round</tt> for the closest value). | ||
+ | |||
+ | Julia also has basic symbolic abilities, beyond numerical ones: | ||
+ | |||
+ | <pre> | ||
+ | julia> 24/9 | ||
+ | 2.6666666666666665 | ||
+ | |||
+ | julia> 24//9 | ||
+ | 8//3 | ||
+ | |||
+ | julia> numerator(1389//234) | ||
+ | 463 | ||
+ | </pre> | ||
+ | |||
+ | Julia knows about important constants: | ||
+ | |||
+ | <pre> | ||
+ | julia> pi | ||
+ | π = 3.1415926535897... | ||
+ | </pre> | ||
+ | |||
+ | It even supports [[unicode]]. We could use such characters using [[LaTeX]] encoding and tab: | ||
+ | |||
+ | <pre> | ||
+ | \alpha+[tab]→α | ||
+ | </pre> | ||
+ | |||
+ | that we can use as a variable. In some cases it could be useful, compare for instance: | ||
+ | |||
+ | <pre> | ||
+ | julia> 5≥2 | ||
+ | true | ||
+ | |||
+ | julia> 5>=2 | ||
+ | true | ||
+ | |||
+ | julia> 5=>2 | ||
+ | 5 => 2 | ||
+ | </pre> | ||
+ | |||
+ | where the top version was input as <tt>\ge+[tab]</tt>. If you know the unicode code, you can enter it as "\uXXXX". For instance: | ||
+ | |||
+ | <pre> | ||
+ | julia> c="\u2020" | ||
+ | "†" | ||
+ | </pre> | ||
+ | |||
+ | By the way, we have just introduced a new type of "variable", that we don't find in maths. So-called strings: | ||
+ | |||
+ | <pre> | ||
+ | julia> hello="Hi there!" | ||
+ | "Hi there!" | ||
+ | |||
+ | julia> hello | ||
+ | "Hi there!" | ||
+ | </pre> | ||
+ | |||
+ | You can somehow "operate" on such things as well. Here's concatenation, or joining strings: | ||
+ | |||
+ | <pre> | ||
+ | julia> hello*" Hey, you!" | ||
+ | "Hi there! Hey, you!" | ||
+ | </pre> | ||
+ | |||
+ | Strings are clearly important in computer programming, as we deal a lot with texts. We shall see concepts such as ''regular expressions'' that allow powerful text processing, e.g., | ||
+ | |||
+ | <pre> | ||
+ | julia> replace("Julia", "a" => "us") | ||
+ | "Julius" | ||
+ | </pre> | ||
+ | |||
+ | But for now, we'll be more concerned on the numerical aspect. In this context, another type of variable that is very useful is the concept of arrays, which is a list or vector. Here's an array of 10 consecutive integers: | ||
+ | |||
+ | <pre> | ||
+ | julia> a = [1:10;] | ||
+ | 10-element Array{Int64,1}: | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 5 | ||
+ | 6 | ||
+ | 7 | ||
+ | 8 | ||
+ | 9 | ||
+ | 10 | ||
+ | </pre> | ||
+ | |||
+ | Things can quickly go from completely obvious to quite tricky. Consider the following: | ||
+ | |||
+ | <pre> | ||
+ | julia> b=a | ||
+ | 10-element Array{Int64,1}: | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 5 | ||
+ | 6 | ||
+ | 7 | ||
+ | 8 | ||
+ | 9 | ||
+ | 10 | ||
+ | |||
+ | julia> b[5]+=1 | ||
+ | 6 | ||
+ | </pre> | ||
+ | |||
+ | We have incremented the 5th element of b by one, so that: | ||
+ | |||
+ | <pre> | ||
+ | julia> b | ||
+ | 10-element Array{Int64,1}: | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 6 | ||
+ | 6 | ||
+ | 7 | ||
+ | 8 | ||
+ | 9 | ||
+ | 10 | ||
+ | </pre> | ||
+ | |||
+ | Now for the tricky part. what do you think happens with: | ||
+ | |||
+ | <pre> | ||
+ | a==b | ||
+ | </pre> | ||
+ | |||
+ | The answer is <tt>true</tt>. This is counterintuitive because with "variables" rather than arrays, we get a different results: | ||
+ | |||
+ | <pre> | ||
+ | julia> α=5 | ||
+ | 5 | ||
+ | |||
+ | julia> β=α | ||
+ | 5 | ||
+ | |||
+ | julia> β+=1 | ||
+ | 6 | ||
+ | |||
+ | julia> α==β | ||
+ | false | ||
+ | </pre> | ||
+ | |||
+ | This is because the command <tt>b=a</tt> does not copy the array <tt>a</tt> into <tt>b</tt> (it does for the variables), but it copied the "address" of the array in memory. If we want to duplicate an independent array, we must do: | ||
+ | |||
+ | <pre> | ||
+ | ulia> b=copy(a) | ||
+ | 10-element Array{Int64,1}: | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | 7 | ||
+ | 6 | ||
+ | 7 | ||
+ | 8 | ||
+ | 9 | ||
+ | 10 | ||
+ | </pre> | ||
+ | |||
+ | Now changing <tt>b[5]</tt> does not change <tt>a[5]</tt>. Be careful of these kinds of subtle things, they are the source of many mistakes (or "bugs", as we call them). | ||
+ | |||
+ | Incrementing a counter is a good way to keep track of what is going, along with control flow. The most famous are: | ||
+ | |||
+ | Let us now play with things computers are good at, to start with, plotting: | ||
− | |||
− | |||
− | |||
− | |||
{{WLP6}} | {{WLP6}} |
Julia is a powerful/efficient/high-level computer programming language. You can get into interacting mode right-away with:
julia
Exit with exit(). One may also also use Wolfram's notebook concept:
jupyter-notebook
We will often need to install packages, which, back to julia, is done as follows:
using Pkg Pkg.add("IJulia")
Then, from a terminal, jupyter-notebook opens a session in a browser, in which one can start a Julia session with a New invocation (and choosing julia there).
There are some conventions in computer programming which become natural as you get used to them. For instance, $x=3$ takes a different meaning in most languages than in Mathematics. In the latter case, it means that the variable $x$ has the same value as the number 3. For a computer x=3 assigns the value 3 to the variable x. In Julia that becomes:
julia> x=3 3
The output 3 is the result of our line of code, which reads: assigns the value 3 to x. The result of this is 3. In maths, if $x=3$, then $x\neq 4$, while in computer code, following x=3, we can have x=4 meaning we now assign the value 4 to x. The computer code equivalent of the mathematical $=$ is actually ==. Indeed:
julia> x=4 4 julia> x==3 false
A typical line of code is to increment the value of a variable, which in many cases we would refer to as a counter:
x=x+1
Note that in Maths, this equality is trivially wrong. In computer code, on the other hand, it is so useful that we even have a special notation for it:
x+=1
Incrementing the value of x and storing the result:
julia> x=4 4 julia> x+=1 5
A very early computer language which defined much of the conventions, notations and overall syntax of computer programming is C. An improved (and modernized) version implementing object-programming is known as C++, implying the joke it's an added version of C.
Most conventions are natural or familiar already
julia> 3>2 true julia> 17<=5 false julia> 1+5!=2+3 true
but some others, we're not even sure we really want them:
julia> 7/2==2\7 true
(this is called inverse division). More useful is the remainder $r$ from Euclidean division $a=bq+r$ which is obtained as a%b, for instance, $17=3\times 5+2$ so
julia> 17%5 2 julia> 17%3 2
so for instance, when we found that it was taking 205s for the computer of a dumb programmer to compute a Fibonacci number, we could give a better idea of the poor performance by giving the time in minutes:
julia> floor(204/60) 3.0 julia> 204%60 25
where we used floor to extract the integer part (to lowest value; we'd use ceil for the highest value and round for the closest value).
Julia also has basic symbolic abilities, beyond numerical ones:
julia> 24/9 2.6666666666666665 julia> 24//9 8//3 julia> numerator(1389//234) 463
Julia knows about important constants:
julia> pi π = 3.1415926535897...
It even supports unicode. We could use such characters using LaTeX encoding and tab:
\alpha+[tab]→α
that we can use as a variable. In some cases it could be useful, compare for instance:
julia> 5≥2 true julia> 5>=2 true julia> 5=>2 5 => 2
where the top version was input as \ge+[tab]. If you know the unicode code, you can enter it as "\uXXXX". For instance:
julia> c="\u2020" "†"
By the way, we have just introduced a new type of "variable", that we don't find in maths. So-called strings:
julia> hello="Hi there!" "Hi there!" julia> hello "Hi there!"
You can somehow "operate" on such things as well. Here's concatenation, or joining strings:
julia> hello*" Hey, you!" "Hi there! Hey, you!"
Strings are clearly important in computer programming, as we deal a lot with texts. We shall see concepts such as regular expressions that allow powerful text processing, e.g.,
julia> replace("Julia", "a" => "us") "Julius"
But for now, we'll be more concerned on the numerical aspect. In this context, another type of variable that is very useful is the concept of arrays, which is a list or vector. Here's an array of 10 consecutive integers:
julia> a = [1:10;] 10-element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10
Things can quickly go from completely obvious to quite tricky. Consider the following:
julia> b=a 10-element Array{Int64,1}: 1 2 3 4 5 6 7 8 9 10 julia> b[5]+=1 6
We have incremented the 5th element of b by one, so that:
julia> b 10-element Array{Int64,1}: 1 2 3 4 6 6 7 8 9 10
Now for the tricky part. what do you think happens with:
a==b
The answer is true. This is counterintuitive because with "variables" rather than arrays, we get a different results:
julia> α=5 5 julia> β=α 5 julia> β+=1 6 julia> α==β false
This is because the command b=a does not copy the array a into b (it does for the variables), but it copied the "address" of the array in memory. If we want to duplicate an independent array, we must do:
ulia> b=copy(a) 10-element Array{Int64,1}: 1 2 3 4 7 6 7 8 9 10
Now changing b[5] does not change a[5]. Be careful of these kinds of subtle things, they are the source of many mistakes (or "bugs", as we call them).
Incrementing a counter is a good way to keep track of what is going, along with control flow. The most famous are:
Let us now play with things computers are good at, to start with, plotting: