-
Book Overview & Buying
-
Table Of Contents
Mastering Julia - Second Edition
By :
An array is an indexable collection of (normally) heterogeneous values such as integers, floats, and Booleans. In Julia, unlike many programming languages, the index starts at 1, not 0.
One-dimensional arrays are also termed vectors and two-dimensional arrays as matrices.
Let’s define the following vector:
julia>A = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610];julia>typeof(A) Vector{Int64} (alias for Array{Int64, 1})
This represents a column array, whereas not using the comma as an element separator creates a row matrix:
julia>A = [1 1 2 3 5 8 13 21 34 55 89 144 233 377 610];julia>typeof(A) Matrix{Int64} (alias for Array{Int64, 2})
We observed these are the first 15 numbers of the well-known Fibonacci sequence.
In conjunction with 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; typeof(A) UnitRange{Int64}julia>B = 1:3:15; typeof(B) StepRange{Int64,Int64}julia>C = 0.0:0.2:1.0; typeof(C) StepRangeLen{Float64,Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}
In Julia, the preceding definition returns a range type.
To convert a range to an array, we have seen previously that it is possible to use the collect() function, as follows:
julia> C = 0.0:0.2:1.0; collect(C)
6-element Vector{Float64}:
0.0
0.2
0.4
0.6
0.8
1.0 Julia also provides functions such as zeros(), ones(), and rand(), which provide array results.
Normally, these functions return floating-point values, so a little bit of TLC is needed to provide integer results, as seen in the following code snippet:
A = convert.(Int64,zeros(15)); B = convert.(Int64,ones(15)); C = convert.(Int64,rand(1:100,15));
The preceding code is an example of broadcasting in Julia, and we will discuss it a little further in the next section.
Originally, the application of operators to members of an array was implemented using a broadcast() function. This led to some pretty unwieldy expressions, so this was simplified by the preceding “dot” notation.
Let’s define a 2x3 matrix of rational numbers and convert them to floats, outputting the result to 4 significant places:
julia>X = convert.(Float64, [11/17 2//9 3//7; 4//13 5//11 6//23]) 2×3 Matrix{Float64}: 0.647059 0.222222 0.428571 0.307692 0.454545 0.26087julia>round.(X, digits=4) 2×3 Matrix{Float64}: 0.6471 0.2222 0.4286 0.3077 0.4545 0.2609
Note that the second statement does not alter the actual precision of the values in X unless we reassign—that is, X = round,(X, digits=4).
Consider the function we plotted in Chapter 1 to demonstrate the use of the UnicodePlots package:
julia> f(x) = x*sin(3.0x)*exp(-0.03x) This does not work when applied to the matrix, as we can see here:
julia> Y = f(X)
ERROR: Dimension Mismatch: matrix is not square: dimensions are (2, 3) But it can be evaluated by broadcasting; in this case, the broadcasting dot follows the function names, and also note that broadcasting can be applied to a function defined by ourselves, not just to built-in functions and operators:
julia> Y = f.(X)
2×3 Matrix{Float64}:
0.591586 0.136502 0.40602
0.243118 0.438802 0.182513 This can also be done without the f() temporary function:
julia> Y = X .* sin.(3.0 .* X) .* exp.(- 0.03 .* X)
2×3 Matrix{Float64}:
0.591586 0.136502 0.40602
0.243118 0.438802 0.182513 Finally, in the following example, we are using the |> operator we met previously and an anonymous function:
julia> X |> (x -> x .* sin.(3.0 .* x) .* exp.(- 0.03 .* x))
2×3 Matrix{Float64}:
0.591586 0.136502 0.40602
0.243118 0.438802 0.182513 This introduces the alternate style (x -> f(x)) as a mapping function, equivalent to the syntax to map (f,X).
Another method of creating and populating an array is by using a list comprehension:
# Using a list comprehension is a bit more cumbersomejulia>Y = zeros(2,3);julia>[Y[i,j] = X[i,j]*sin(3.0*X[i,j])*exp(-0.03*X[i,j]) for i=1:2 for j=1:3];julia>Y 2×3 Matrix{Float64}: 0.591586 0.136502 0.40602 0.243118 0.438802 0.182513
There are cases where a list comprehension is useful—for example, to list only odd values of the Fibonacci series, we can use the following statement:
julia> [fac(k) for k in 1:9 if k%2 != 0]
5-element Vector{BigInt}:
1
6
120
5040
362880 For the moment, armed with the use of arrays, we will look at recursion and how this is implemented in Julia.