Crash Course in Scientific Computing

IV. Julia

Julia is a powerful/efficient/high-level computer programming language. You can get into interacting mode right-away with:

julia

Julia-Screenshot 21-02-2020 181505.jpg

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: