- Mastering Julia
- Malcolm Sherrington
- 1185字
- 2021-07-16 13:42:40
Arrays
An array is an indexable collection of (normally) homogeneous values such as integers, floats, booleans. In Julia, unlike many programming languages, the index starts at 1
not 0
.
One simple way to create an array is to enumerate its values:
julia> A = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]; 15-element Array{Int64,1}
These are the first 15 values of the Fibonacci series and because all values are listed as integers the array created is of type Int64
. The other number refers to the number of dimensions of the array, in this case 1.
In conjunction of loops in the Asian option example in the previous chapter, we meet the definition of a range as: start:[step]:end
julia> A = [1:10]; B = [1:3:15]; C =[1:0.5:5];
Here A
is [1,2,3,4,5,6,7,8,9,10]
, B
is [1,4,7,10,13]
and C is [1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0]
Because the step in C
is specified as a float value the array is of type Float64
not Int64
.
Julia also provides functions such as zeros
, ones
and rand
which provide array results. Normally these are returned a float-point value so a little bit of work is required to provide integer results.
julia> A = int(zeros(15)); B = int(ones(15)); C = rand(1:100,15);
Another method of creating and populating an array is by using a list comprehension. If we recall the first example of the Fibonacci series, we can get the same result by creating an uninitialized array of 15 integers by using Array(Int64,15)
then by assigning the first couple of values and use the definition of the Fibonacci series to create the remaining values:
julia> A = Array(Int64,15); A[1]=0;A[2]=1;[A[i] = A[i-1] + A[i-2] for i = 3:length(A)]
Finally it is possible to create a completely empty array by using Int64[]
. Since array sizes are fixed this would seem a little futile but certain functions can be used to alter the size of the array. In particular the push!()
function can add a value to the array and increase its length by one:
julia> A = Int64[]; julia> push!(A,1); push!(A,2); push!(A,3) # => [1,2,3]
The corresponding pop!(A)
function will return the value 3
, and result in A = [1,2]
.
Note that the use of the tailing !
borrows the syntax form Lisp-like conventions and is purely arbitrary. Since functions are first class variables this is the reason that !
is an accepted character in variable names but it's a good idea to respect the convention and not use !
in reference to common variables.
Consider the following two array definitions:
julia> A = [1,2,3]; 3-element Array{Int64,1} julia> A = [1 2 3]; 1x3 Array{Int64,2}
The first, with values separated by commas, produces the usual one-dimensional data structure. The second, where there are no commas, produces a matrix or 1 row and 3 columns, hence the definition: 1x3 Array{Int64,2}
.
To define more rows we separate the values with semicolons as:
julia> A = [1 2 3; 4 5 6] 2x3 Array{Int64,2} 1 2 3 4 5 6
If we type:
for i in (1:length(A)) @printf("%1d: %1d\n", i, A[i]); end 1 : 1 2 : 4 3 : 2 4 : 5 5 : 3 6 : 6
In Julia indexing is in column order and the array/matrix can be indexed in a one-dimensional or two-dimensional.
julia> A[1,2] # => 2 julia> A[2] # => 4 julia> A[5]# => 3
In fact it is possible to reshape the array to change it from a 2x3
matrix to a 3x2
one:
julia> B = reshape(A,3,2) 3x2 Array{Int64,2}: 1 5 4 3 2 6
Operations on matrices
We will be meeting matrices and matrix operations through this book but let us look at the simplest of operations:
Taking A
and B
as defined previously the normal matrix rules apply.
We'll define C
as the transpose of B
so:
julia> C = transpose(B) 2x3 Array{Int64,2}: 1 4 2 5 3 6 julia> A + C 2x3 Array{Int64,2}: 2 6 5 9 8 12 julia> A*B 2x2 Array{Int64,2}: 15 29 36 71
Matrix pision makes more sense with square matrices but it is possible to define the operations for non-square matrices too:
julia> A / C 2x2 Array{Float64,2} 0.332273 0.27663 0.732909 0.710652
Elemental operations
As well as the 'common' matrix operations, Julia defines a set which works on the elements of the matrix. So although A * C
is not allowed because number of columns of A
is not equal to number of rows of C
but the following are all valid since A
and C
are the same shape:
julia> A .* C 2x3 Array{Int64,2}: 1 8 6 20 15 36 julia> A ./ C 2x3 Array{Float64,2}: 1.0 0.5 1.5 0.8 1.66667 1.0 julia> A .== C 2x3 BitArray{2}: true false false false false true
A simple Markov chain – cat and mouse
Suppose there is a row of five adjacent boxes, with a cat in the first box and a mouse in the fifth box. At each 'tick' the cat and the mouse both jump to a random box next to them. On the first tick the cat must jump to box 2 and the mouse to box 4 but on the next ticks they may jump to the box they started in or to box 3.
When the cat and mouse are in the same box the cat catches the mouse and the Markov chain terminates. Because there is an odd number of boxes between the cat and mouse it's easy to see that they will not jump past each other.
So Markov chain that corresponds to this contains the only five possible combinations of (Cat,Mouse)
.
State 1: (1,3) State 2: (1,5) State 3: (2,4) State 4: (3,5) State 5: (2,2), (3,3) & (4,4) # => cat catches the mouse
The matrix P = [0 0 .5 0 .5; 0 0 1 0 0; .25 .25 0, .25 .25; 0 0 .5 0 .5; 0 0 0 0 1]
represents the probabilities of the transition from one state to the next and the question is how long has the mouse got before it's caught. Its best chance is starting in State 2 = (1,5)
.
The matrix P
is a stochastic matrix where all the probabilities along any row add up to 1.
This is actually an easy problem to solve using some matrix algebra in a few lines in Julia and for a full discussion of the problem look at the Wikipedia discussion.
I = eye(4); P = [0 0 .5 0; 0 0 1 0; .25 .25 0 .25; 0 0 .5 0]; ep = [0 1 0 0]*inv(I - P)*[1,1,1,1]; println("Expected lifetime for the mouse is $ep ticks") Expected lifetime for the mouse is [4.5] ticks
Consider how this works:
- The
eye()
function returns a square(real) matrix with leading diagonal unity and the other values of zero. - The matrix
P
can be reduced to4x4
since when in state5
the Markov chain terminates. - The
inv(I - P)*[1,1,1,1]
returns the expected lifetime (no disrespect) of the mouse in all states so multiplying with[0 1 0 0]
gives the expectation when starting in state2.0
.
- Getting Started with Gulp(Second Edition)
- Mastering Adobe Captivate 2017(Fourth Edition)
- CMDB分步構(gòu)建指南
- Rake Task Management Essentials
- 算法精粹:經(jīng)典計算機科學問題的Python實現(xiàn)
- GitLab Repository Management
- 深入理解Java7:核心技術(shù)與最佳實踐
- Groovy for Domain:specific Languages(Second Edition)
- Learning Python Design Patterns
- Getting Started with Gulp
- OpenCV 3 Blueprints
- Mastering OAuth 2.0
- 零基礎(chǔ)學Java第2版
- PHP Microservices
- MongoDB Cookbook