Linguagem de Programação Matemática - Introdução à Julia

Julia é uma linguagem dinâmica de alto nível e alto desempenho. Ela se assemelha ao MatLab e ao Python na facilidade de escrita de código, mas sua velocidade pode ser comparável ao C e Fortran.

Jupyter

O Jupyter é uma interface web para Julia, Python, e muitas outras. Ela não é o Julia, isto é, o Julia não depende do Jupyter para funcionar. No entanto, usando o Jupyter, aulas e apresentações ficam mais práticas.

Cada célula do Jupyter pode ser executada com um ctrl+enter, ou um shift+enter, sendo que o último move a seleção para a célula de baixo. Você pode adicionar novas células usando o + no topo da página.

O REPL - Terminal Interativo

Ao abrir o Julia no Windows, ou digitar julia no terminal do Mac ou Linux, se abrirá um prompt tipo

julia>

O Jupyter também serve como esse prompt e todo comando digitado aqui pode ser digitado lá.

Editor: VSCode

A fazer...

Jupyter vs Editor

O Jupyter é utilizado para aulas, apresentações, workshops. A parte importante é a interatividade.

O editor é usado para fazer códigos sérios. Para desenvolver os exercícios, projetos, e futuros pacotes, é necessário criar arquivos e ter um ambiente adequado.

Os exercícios e projetos devem ser feitos num editor e serão avaliados sem o uso do Jupyter.

Introdução à Julia

MersenneTwister(0)

Básico

2 + 3 + 5 + 7 + 11
28
3 * 5
15
7 ^ 3
343
exp(-1) * exp(1)
1.0
( sin(3.14159/4) * 2 )^2
1.9999973464102065
pi
π = 3.1415926535897...
( sin(pi/4) * 2 )^2
1.9999999999999996
round(1.2)
1.0
abs(-3)
3
log(2)
0.6931471805599453
log10(2) + log10(5)
1.0
log2(2)
1.0
x = 3
3
x ^ 2
9
y = 2x
6
y
6
y - x
3
1e-2 # 10⁻²
0.01
1e3 # 10³
1000.0
3.45e2
345.0
0.1 + 0.2 - 0.3
5.551115123125783e-17

Exercício

Sabendo que sqrt é a função que calcula a raiz quadrada, calcule \( \dfrac{1 + \sqrt{5}}{2}. \)

(1 + sqrt(5)) / 2
1.618033988749895

Álgebra Linear Numérica

[1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4
[4.0 3; 2 1]
2×2 Matrix{Float64}:
 4.0  3.0
 2.0  1.0
[2.0 3.0 4.0 5.0]
1×4 Matrix{Float64}:
 2.0  3.0  4.0  5.0
rand(3)
3-element Vector{Float64}:
 0.8236475079774124
 0.9103565379264364
 0.16456579813368521
rand(2, 3)
2×3 Matrix{Float64}:
 0.177329  0.203477   0.0682693
 0.27888   0.0423017  0.361828
ones(3)
3-element Vector{Float64}:
 1.0
 1.0
 1.0
zeros(3)
3-element Vector{Float64}:
 0.0
 0.0
 0.0
rand(2,4)
2×4 Matrix{Float64}:
 0.973216  0.539289  0.910047  0.655448
 0.585812  0.260036  0.167036  0.575887
v = rand(3)
3-element Vector{Float64}:
 0.8682787096942046
 0.9677995536192001
 0.7676903325581188
A = rand(2, 3)
2×3 Matrix{Float64}:
 0.469304   0.353129  0.043141
 0.0623676  0.767602  0.267985
A * v
2-element Vector{Float64}:
 0.7823632343523121
 1.002766408376991
w = rand(2)
2-element Vector{Float64}:
 0.06684644402498341
 0.15663663731366406
A' * w
3-element Vector{Float64}:
 0.04114032872722164
 0.14383998251721294
 0.044860035999713756
A' * A
3×3 Matrix{Float64}:
 0.224136   0.213598  0.0369598
 0.213598   0.713913  0.22094
 0.0369598  0.22094   0.0736769
B = rand(2, 3)
2×3 Matrix{Float64}:
 0.605297  0.838118  0.300075
 0.135745  0.914712  0.72285
A + B
2×3 Matrix{Float64}:
 1.0746    1.19125  0.343216
 0.198112  1.68231  0.990834
A * B'
2×2 Matrix{Float64}:
 0.592977  0.417901
 0.761507  0.904313
A' * B
3×3 Matrix{Float64}:
 0.292534   0.45038   0.185909
 0.317945   0.998098  0.660826
 0.0624906  0.281286  0.206658
A = rand(3, 3)
b = rand(3)
x = A \ b # Resolve o SL
3-element Vector{Float64}:
 -1.515890567498096
  2.1839037981597493
  0.22954922712702647
inv(A) * b
3-element Vector{Float64}:
 -1.515890567498096
  2.183903798159749
  0.22954922712702644
A * x - b # É pra ser zero (ou quase)
3-element Vector{Float64}:
 -2.7755575615628914e-17
 -1.8041124150158794e-16
 -1.1102230246251565e-16
using LinearAlgebra

norm(A * x - b) # norm = ‖ ⋅ ‖
2.1364582767275725e-16
v = [1.0; 2.0; 3.0]
w = [2.0; -2.0; 2.0]
dot(v, w) # ⟨v,w⟩
4.0
v * w'
3×3 Matrix{Float64}:
 2.0  -2.0  2.0
 4.0  -4.0  4.0
 6.0  -6.0  6.0
cross(v, w)
3-element Vector{Float64}:
 10.0
  4.0
 -6.0
det(A)
0.22689437481041141
A^2 # A * A
3×3 Matrix{Float64}:
 0.804612  0.877119  0.260504
 1.10599   0.982373  1.21788
 0.885398  0.575941  1.499
A .^ 2 # Cada elemento de A ao quadrado
3×3 Matrix{Float64}:
 0.0143167  0.00124924  0.905715
 0.588396   0.234896    0.641791
 0.643081   0.808559    0.0154561
B = rand(3, 3)
3×3 Matrix{Float64}:
 0.104823  0.312145  0.654922
 0.838075  0.196407  0.586712
 0.184115  0.873581  0.632696
A .* B
3×3 Matrix{Float64}:
 0.0125423  0.0110326  0.623283
 0.642862   0.0951909  0.470026
 0.147646   0.785523   0.0786584
v
3-element Vector{Float64}:
 1.0
 2.0
 3.0
w
3-element Vector{Float64}:
  2.0
 -2.0
  2.0
v .^ w
3-element Vector{Float64}:
 1.0
 0.25
 9.0

Funções que normalmente seriam aplicadas a um único elemento podem ser aplicadas a vetores e matrizes utilizando o .

log(2)
0.6931471805599453
log.(A)
3×3 Matrix{Float64}:
 -2.12316   -3.34261   -0.0495152
 -0.265178  -0.724307  -0.221746
 -0.220742  -0.106251  -2.08487
exp(A) # Significa outra coisa
3×3 Matrix{Float64}:
 1.79466  0.6877   1.43864
 1.81472  2.40335  1.94119
 1.69913  1.60044  2.30852
exp.(A) # Elemento a elemento
3×3 Matrix{Float64}:
 1.12711  1.03598  2.59009
 2.15345  1.62362  2.22803
 2.22983  2.45763  1.13238
A + 10I
3×3 Matrix{Float64}:
 10.1197     0.0353445   0.951691
  0.76707   10.4847      0.801119
  0.801924   0.899199   10.1243
A .+ 1
3×3 Matrix{Float64}:
 1.11965  1.03534  1.95169
 1.76707  1.48466  1.80112
 1.80192  1.8992   1.12432
m, n = size(A)
(3, 3)
length(v)
3
size(v)
(3,)
length(A)
9

Exercício

  1. Crie uma matriz A 50 por 50 aleatório, e defina b como o produto dessa matriz pelo vetor composta apenas de uns (1).

  2. Resolva o sistema Ax = b com a matriz A e o vetor b acima, e verifique que a solução é o vetor de uns.

Q1:

A = rand(50, 50)
b = A * ones(50);

Q2:

x = A \ b
norm(x .- 1)
6.29238916693866e-14

Acesso aos elementos

v
3-element Vector{Float64}:
 1.0
 2.0
 3.0
v[1]
1.0
v[2]
2.0
A = rand(3, 3)
3×3 Matrix{Float64}:
 0.476883  0.0491219  0.842256
 0.602375  0.482761   0.169107
 0.791346  0.665252   0.938857
A[1,1]
0.47688264487569976
A[2,3]
0.16910729451857898
v[1:2]
2-element Vector{Float64}:
 1.0
 2.0
A[:,2]
3-element Vector{Float64}:
 0.04912193901316875
 0.48276146782949847
 0.6652515059404427
A[1,:]
3-element Vector{Float64}:
 0.47688264487569976
 0.04912193901316875
 0.8422557594578175
A[2,3] = 0.0
0.0
A
3×3 Matrix{Float64}:
 0.476883  0.0491219  0.842256
 0.602375  0.482761   0.0
 0.791346  0.665252   0.938857

Exercício

1. Crie um vetor aleatório e mude o primeiro elemento para o seu oposto (i.e. mude o sinal)

v = rand(5)
v[1] = -v[1]
-0.7837260309016443

Matriz por blocos - Concatenação

A = rand(3, 3)
3×3 Matrix{Float64}:
 0.505874  0.0682234  0.452457
 0.39206   0.479948   0.644211
 0.479356  0.468397   0.669275
B = rand(3, 2)
3×2 Matrix{Float64}:
 0.0947919  0.177409
 0.948884   0.0800227
 0.775188   0.682194
[A B] # Mesma linha
3×5 Matrix{Float64}:
 0.505874  0.0682234  0.452457  0.0947919  0.177409
 0.39206   0.479948   0.644211  0.948884   0.0800227
 0.479356  0.468397   0.669275  0.775188   0.682194
[A A A]
3×9 Matrix{Float64}:
 0.505874  0.0682234  0.452457  0.505874  0.0682234  0.452457  0.505874  0.0682234  0.452457
 0.39206   0.479948   0.644211  0.39206   0.479948   0.644211  0.39206   0.479948   0.644211
 0.479356  0.468397   0.669275  0.479356  0.468397   0.669275  0.479356  0.468397   0.669275
[A; B'] # Mesma coluna
5×3 Matrix{Float64}:
 0.505874   0.0682234  0.452457
 0.39206    0.479948   0.644211
 0.479356   0.468397   0.669275
 0.0947919  0.948884   0.775188
 0.177409   0.0800227  0.682194
[A, B] # NÃO É CONCATENAÇÃO
2-element Vector{Matrix{Float64}}:
 [0.5058741376644247 0.06822341709242075 0.45245669115936304; 0.39206003754122043 0.4799481236784777 0.6442110258372615; 0.47935649090647914 0.4683970163381419 0.6692753552886208]
 [0.09479186551379559 0.17740896332315637; 0.9488838151206662 0.08002265274552212; 0.7751879774225319 0.6821935901697289]
[A B; B' zeros(2,2)]
5×5 Matrix{Float64}:
 0.505874   0.0682234  0.452457  0.0947919  0.177409
 0.39206    0.479948   0.644211  0.948884   0.0800227
 0.479356   0.468397   0.669275  0.775188   0.682194
 0.0947919  0.948884   0.775188  0.0        0.0
 0.177409   0.0800227  0.682194  0.0        0.0
[A I]
3×6 Matrix{Float64}:
 0.505874  0.0682234  0.452457  1.0  0.0  0.0
 0.39206   0.479948   0.644211  0.0  1.0  0.0
 0.479356  0.468397   0.669275  0.0  0.0  1.0
[A; I]
6×3 Matrix{Float64}:
 0.505874  0.0682234  0.452457
 0.39206   0.479948   0.644211
 0.479356  0.468397   0.669275
 1.0       0.0        0.0
 0.0       1.0        0.0
 0.0       0.0        1.0

Funções

Existem três maneiras de definir uma função. Uma básica, quase matemática:

f(x) = x * exp(-x)
f(2)
0.2706705664732254
f(-3)
-60.256610769563004
f(sqrt(2))
0.34381898307672376
g(a,b) = exp(a + b)
g (generic function with 1 method)
g(2,3)
148.4131591025766
exp(5)
148.4131591025766
g(3,-3)
1.0

Uma maneira anônima

2
2
x -> sin(x) * x
#1 (generic function with 1 method)
(x -> sin(x) * x)(pi/4)
0.5553603672697958

Que podemos atribuir a uma variável

h = x -> sin(x) * x
#5 (generic function with 1 method)
h(pi/4)
0.5553603672697958

A última usa function e end para definir uma função com nome e definição extensa (o jeito tradicional). É o jeito mais descritivo, apesar de ser o mais longo.

function media(a, b)
    return (a + b) / 2
end
media (generic function with 1 method)
media(7, 4)
5.5
function reverte(a, b)
    return b, a
end
reverte (generic function with 1 method)
reverte(5, 3)
(3, 5)
function aproxima_derivada(f, a, h)
    Δf = f(a + h) - f(a)
    return Δf / h
end
aproxima_derivada (generic function with 1 method)
aproxima_derivada(exp, 1.0, 1e-6)
2.7182831874306146
s(x) = sin(x)
s (generic function with 1 method)
aproxima_derivada(s, pi/6, 1e-8)
0.8660254013914681
sqrt(3) / 2
0.8660254037844386
aproxima_derivada(x->x^2 + 3x + 2, 2, 1e-4)
7.000100000027487

Além dos argumentos obrigatórios de uma função, também podemos adicionar argumentos posicionais opcionais, e argumentos por palavra chave.

#Aqui p é opcional
function potencia(x, p=1)
    return x^p
end
potencia (generic function with 2 methods)
potencia(2)
2
potencia(2, 2)
4
potencia(2, 10)
1024
potencia(2.0, 10)
1024.0
A = rand(2,2)
2×2 Matrix{Float64}:
 0.92936   0.651778
 0.973119  0.596532
potencia(A, 4)
2×2 Matrix{Float64}:
 3.72067  2.47449
 3.69448  2.45708
potencia.(A, 10)

#Aqui, p1 e p2 são opcionais por palavra-chave
function media(a, b; p1 = 1.0, p2 = 1.0)
    return (a * p1 + b * p2) / (p1 + p2)
end
media (generic function with 1 method)
media(2.0, 5.0)
3.5
media(2.0, 5.0, p1=2)
3.0
media(2.0, 5.0, p2=3)
4.25
media(2.0, 5.0, p1=2, p2=3)
3.8

Exercícios

  1. Crie um vetor com os ângulos importantes: \(0\), \(\frac{\pi}{6}\), \(\frac{\pi}{4}\), \(\frac{\pi}{3}\) e \(\frac{\pi}{2}\).

  2. Crie um vetor com o seno de cada ângulo e outro com o cosseno, usando o vetor acima.

  3. Calcule a tangente de cada angulo usando os dois vetores acima (tan = sen/cos)

  4. Crie uma função que recebe uma matriz \(A\) e um vetor \(v\) e retorna

\[\dfrac{\langle v, Av\rangle}{\langle v, v\rangle}.\]
  1. Teste com a matriz

\[\begin{bmatrix} 6 & 1 \\ 1 & 4\end{bmatrix}.\]

e o vetor de uns.

θ = [0.0; π / 6; π / 4; π / 3; π / 2]
seno, cosseno = sin.(θ), cos.(θ)
tangente = seno ./ cosseno
5-element Vector{Float64}:
 0.0
 0.5773502691896256
 0.9999999999999999
 1.7320508075688767
 1.633123935319537e16
[seno cosseno]
5×2 Matrix{Float64}:
 0.0       1.0
 0.5       0.866025
 0.707107  0.707107
 0.866025  0.5
 1.0       6.12323e-17
1 / 0
Inf
function rayleigh(A, v)
    return dot(v, A * v) / dot(v, v)
end
rayleigh (generic function with 1 method)
A = [6 1; 1 4]
v = ones(2)
rayleigh(A, v)
6.0
v = rand(2)
rayleigh(A, v)
6.2251540877058575

Loops e condicionais

Quase todas as linguagens de programação usam loops e condicionais, sendo os principais:

  • for, que itera sobre um conjunto finito de elementos;

  • if, que verifica uma condição e executa partes de códigos diferentes dependendo do resultado;

  • while, que repete comandos até encontrar uma condição;

A ideia é a mesma em todas as linguagens, mas a sintaxe muda.

1:5
1:5
collect(1:5)
5-element Vector{Int64}:
 1
 2
 3
 4
 5
collect(1:2:5)
3-element Vector{Int64}:
 1
 3
 5
collect(0.0:0.1:1.0)
11-element Vector{Float64}:
 0.0
 0.1
 0.2
 0.3
 0.4
 0.5
 0.6
 0.7
 0.8
 0.9
 1.0
collect(range(0, 1, length=11))
11-element Vector{Float64}:
 0.0
 0.1
 0.2
 0.3
 0.4
 0.5
 0.6
 0.7
 0.8
 0.9
 1.0
range(0, stop=1, step=0.5)
0.0:0.5:1.0
collect(10:-1:1)
10-element Vector{Int64}:
 10
  9
  8
  7
  6
  5
  4
  3
  2
  1
for i = 2.0:0.5:3.0
    println(i^2) # Impressão e quebra linha
end
4.0
6.25
9.0
for i = 1:10
    print(i, " ")
end
1 2 3 4 5 6 7 8 9 10 
for i = 1:10
    println("i = $i")
end
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10
using Printf
for i = 1:10
    @printf("i = %010.4e\n", i / 7) # Notação de C
end
i = 1.4286e-01
i = 2.8571e-01
i = 4.2857e-01
i = 5.7143e-01
i = 7.1429e-01
i = 8.5714e-01
i = 1.0000e+00
i = 1.1429e+00
i = 1.2857e+00
i = 1.4286e+00
x = rand(10)
y = zeros(10)
for i = 1:10
    y[i] = x[i] * i
end
[x y]
10×2 Matrix{Float64}:
 0.470637   0.470637
 0.382453   0.764906
 0.97655    2.92965
 0.216105   0.864421
 0.86319    4.31595
 0.0653417  0.39205
 0.69999    4.89993
 0.850205   6.80164
 0.714589   6.4313
 0.439458   4.39458
y ./ x
10-element Vector{Float64}:
  1.0
  2.0
  3.0
  4.0
  5.000000000000001
  6.0
  6.999999999999999
  8.0
  9.0
 10.0
for x in [0; pi/6; pi/4; pi/3; pi/2]
    println("sin($x) = $(sin(x))")
end
sin(0.0) = 0.0
sin(0.5235987755982988) = 0.49999999999999994
sin(0.7853981633974483) = 0.7071067811865475
sin(1.0471975511965976) = 0.8660254037844386
sin(1.5707963267948966) = 1.0
for i = 3:3:20
    print("$i ")
end
3 6 9 12 15 18 
for i in 3:2:10
    println("$i^2 = $(i^2)")
end
3^2 = 9
5^2 = 25
7^2 = 49
9^2 = 81

Tipos importam

Todos objetos em Julia tem um tipo. Assim como números podem ser reais, inteiros, etc, um número em Julia pode ser Real, Integer, ou tipos ainda mais específicos, como Float64, Int64, ComplexF64, Rational, etc.

Além disso, funções tem tipo Function, vetores e matrizes têm tipos também, texto tem tipo String, onde String originalmente se referente à cadeia de caracteres, e Char é o tipo para caractere.

Tipos têm hierarquia, e tipo mais geral é Any.

[2; 3]
2-element Vector{Int64}:
 2
 3
Float64[2; 3]
2-element Vector{Float64}:
 2.0
 3.0
for x in Any["a", 'b', 0, 3.14, true, MathConstants.e, 3//4, im, ones(2), ones(2,2)]
    println("x: $x    Tipo: $(typeof(x))")
end
x: a    Tipo: String
x: b    Tipo: Char
x: 0    Tipo: Int64
x: 3.14    Tipo: Float64
x: true    Tipo: Bool
x: ℯ    Tipo: Irrational{:ℯ}
x: 3//4    Tipo: Rational{Int64}
x: im    Tipo: Complex{Bool}
x: [1.0, 1.0]    Tipo: Vector{Float64}
x: [1.0 1.0; 1.0 1.0]    Tipo: Matrix{Float64}
n = 6
v = ones(n)
v[n/2] = 2 #Erro esperado
ArgumentError: invalid index: 3.0 of type Float64
n/2
3.0
div(n,2)
3
div(7, 2)
3
round(Int, n/2)
3
10 % 4 # Resto da divisão de 10 por 4
2

Fatorial: \( n! = n(n-1)\dots2. 1 \)

function fatorial(n)
    resultado = 1
    for i = 1:n
        resultado = resultado * i
    end
    return resultado
end
fatorial (generic function with 1 method)
fatorial(4)
24
fatorial(5)
120
fatorial(0)
1
fatorial(4.3) # Nossa implementação não "liga" pra .3
24.0
fatorial(-2) # Nossa implementação
1
function fatorial2(n :: Int)
    resultado = 1
    for i = 1:n
        resultado = resultado * i
    end
    return resultado
end
fatorial2 (generic function with 1 method)
fatorial2(5)
120
fatorial2(3.4)
MethodError: no method matching fatorial2(::Float64)
Closest candidates are:
  fatorial2(!Matched::Int64) at none:1

sinal:

\[\text{sinal}(x) = \left\{\begin{array}{rl} 1, & x > 0 \\ -1, & x < 0 \\ 0, & x = 0. \end{array}\right.\]
function sinal(x)
    if x > 0
        return 1
    elseif x < 0
        return -1
    else
        return 0
    end
end
sinal (generic function with 1 method)
sinal(3.2)
1
sinal(-1.2)
-1
sinal(0.0)
0

Bháskara:

\[ax^2 + bx + c = 0\]

e

\[b^2 - 4ac \geq 0\]

implicam em :

\[x = \dfrac{-b \pm \sqrt{b^2 - 4ac}}{2a}.\]
function bhaskara(a, b, c)
    Δ = b^2 - 4 * a * c
    if Δ < 0
        error("Nos reais não tem solução")
    end
    return (-b + sqrt(Δ)) / 2a, (-b - sqrt(Δ)) / 2a
end
bhaskara (generic function with 1 method)
bhaskara(1, 0, -1)
(1.0, -1.0)
bhaskara(1, 0, 1)
Nos reais não tem solução
bhaskara(1.0, 5.0, 6.0)
(-2.0, -3.0)
bhaskara(0, 1, 1)
(NaN, -Inf)
Inf / Inf
NaN
(NaN * 2 - Inf - NaN) / NaN
NaN

Maior potência de 2 menor ou igual que um número

function maior_pot(x)
    p = 1
    while p <= x
        p = 2p
    end
    p = div(p, 2)
    return p
end
maior_pot (generic function with 1 method)
maior_pot(2)
2
maior_pot(10)
8
maior_pot(100)
64
for n = [1, 10, 100, 1000, 10000, 100000, 1000000]
    p = maior_pot(n)
    println("2ᵏ = p ≤ n, n = $n, p = $p")
end
2ᵏ = p ≤ n, n = 1, p = 1
2ᵏ = p ≤ n, n = 10, p = 8
2ᵏ = p ≤ n, n = 100, p = 64
2ᵏ = p ≤ n, n = 1000, p = 512
2ᵏ = p ≤ n, n = 10000, p = 8192
2ᵏ = p ≤ n, n = 100000, p = 65536
2ᵏ = p ≤ n, n = 1000000, p = 524288

MMC: \(\text{mmc}(a, b)\) é o menor número natural que é múltiplo de a e de b.

Operadores lógicos:

or → || and → && <> → != = → == (Pascal) Comparação

function mmc(a::Int, b::Int)
    if a < 1 || b < 1
        error("Entrada deve ser de dois inteiros positivos")
    end
    xa, xb = a, b # Múltiplos de a e b
    while (xa != xb) # Não preciso dos parenteses
        if xa < xb
            xa = xa + a
        else
            xb = xb + b
        end
    end
    return xa
end
mmc (generic function with 1 method)
mmc(2,3)
6
mmc(5, 7)
35
mmc(6, 8)
24
mmc(12, 14)
84
mmc(3, 5)
15
mmc(-1, 2)
Entrada deve ser de dois inteiros positivos
mmc(2.0, 3.0)
MethodError: no method matching mmc(::Float64, ::Float64)

Exercícios

  1. Atualize a função fatorial para proibir números negativos não inteiros. Proíba também o fatorial de um número maior que 20.

  2. Atualize a função de Bháskara para que retorne um erro caso a seja 0.

  3. Faça uma função que recebe um inteiro n e verifica se ele é primo.

function fatorial3(n :: Int)
    if n ≤ -1
        error("ERRO: Fatorial só está definido para números ≥ 0")
    end
    if n ≥ 20
        error("ERRO: Fatorial de $n explode")
    end
    resultado = 1
    for i = 1:n
        resultado = resultado * i
    end
    return resultado
end
fatorial3 (generic function with 1 method)
function bhaskara(a, b, c)
    if a == 0
        error("ERRO: Não é quadrática")
    end
    Δ = b^2 - 4 * a * c
    if Δ < 0
        error("Nos reais não tem solução")
    end
    return (-b + sqrt(Δ)) / 2a, (-b - sqrt(Δ)) / 2a
end
bhaskara (generic function with 1 method)
function ehprimo(n::Int)
    if n == 1
        return false
    end
    for k = 2:n-1
        if n % k == 0
            return false
        end
    end
    return true
end
ehprimo (generic function with 1 method)

Arquivos

Quando trabalhamos com mais de um arquivo, o que deve acontecer logo, precisamos incluir um arquivo no outro para obter as informações relevantes.

Além disso, se quisermos rodar as informações do arquivo direto no terminal do Julia, também podemos incluir o arquivo direto do terminal do Julia.

Use:

include("arquivo.jl")

para incluir um arquivo e rodar todo seu conteúdo.

O arquivo precisa estar na mesma pasta do outro arquivo ou do terminal.

Pacotes

O Julia não vem com tudo pré-instalado, assim como a maioria das linguagem de programação. Para encontrar um pacote que faça o que você quer, você pode buscar na lista http://pkg.julialang.org/ ou no Google. Os pacotes que usaremos aqui estarão disponíveis no LAMIND.

Instalação de pacotes –––––––––––––––––––––––

No Julia, aperte ] para entrar no modo pkg>. Use add Pacote para adicionar o pacote com nome Pacote.

Principais pacotes:

  • Pacote Plots: comandos unificados de fazer gráficos.

  • Pacote PyPlot: para desenhar gráficos usando o matplotlib. Bonito, mas lento e demorado de instalar.

  • Pacote GR: outro pacote para desenhar gráficos. Mais rápido, mas menos bonito.

  • Pacote Primes: pacote para trabalhar com números primos.

  • Pacote Combinatorics: pacote para funções de combinátoria.

Plots

Utilizaremos os pacotes Plots e GR para fazer nossos gráficos.

Para o help dos gráficos, veja Julia Plots (https://juliaplots.github.io).

using Plots
gr(size=(600,400))
plot([1; 2; 3], [3; 1; 2]) # plot(x, y)
x = range(0, 1, length=100) # 100 elementos igual. esp. de 0 a 1
y = x.^2
plot(x, y)
scatter(x, x .* (1 .- x) * 4)
scatter(x, rand(100))
f(x) = x * sin(x)
plot(f, 0, 4pi) # plot(f, a, b)
plot(x->exp(x) * x, -1, 1)
plot!(x->exp(-x), -1, 1)
xlims!(-0.5, 0.5)
ylims!(0.5, 1.5)
t = range(-2, stop=3, length=200)
x = cos.(t*pi*2) .* exp.(t)
y = sin.(t*pi*2) .* exp.(t)
plot(x, y)
xlims!(-20, 30)
ylims!(-30, 20)
plot(sin, 0, 2pi, label="sin")
plot!(cos, 0, 2pi, label="cos", c = :magenta)
plot!(x->1, 0, 2pi, c=:red, l=:dash, label="")
plot!(x->-1, 0, 2pi, c=:red, l=:dash, label="")
xlabel!("x in [0,2pi]")
ylabel!("sin, cos")
title!("Funções seno e cosseno")
ylims!(-1.2, 1.2)
xticks!(0:pi/2:2pi, ["0", "\\pi /2", "\\pi", "3\\pi/2", "2\\pi"])
x = range(0, stop=2*pi, length=100)
anim = Animation()
for i = 1:5:100
    plot(x[1:i], sin.(x[1:i]))
    frame(anim)
end
Plots.AnimatedGif("/home/runner/work/calculo-numerico/calculo-numerico/__site/assets/intro-a-julia/code/output/exemplo-1.gif")
x = range(0, stop=2*pi, length=100)
anim = Animation()
for i = 1:3:100
    plot(x[1:i], sin.(x[1:i]))
    xlims!(x[1], x[end])
    ylims!(-1, 1)
    frame(anim)
end
Plots.AnimatedGif("/home/runner/work/calculo-numerico/calculo-numerico/__site/assets/intro-a-julia/code/output/exemplo-2.gif")
x = range(0, stop=2*pi, length=100)
anim = Animation()
for i = 1:3:100
    plot(x, sin.(x), leg=false)
    a = x[i]
    scatter!([a], [sin(a)], c=:red)
    plot!(x, sin(a) .+ cos(a) * (x .- a), c=:red, l=:dash)
    xlims!(x[1], x[end])
    ylims!(-2, 2)
    frame(anim)
end
Plots.AnimatedGif("/home/runner/work/calculo-numerico/calculo-numerico/__site/assets/intro-a-julia/code/output/exemplo-3.gif")
x = range(0, stop=2*pi, length=100)
anim = Animation()
for i = 1:3:100
    plot(x, sin.(x), leg=false)
    a = x[i]
    scatter!([a], [sin(a)], c=:red)
    plot!(x, sin(a) .+ cos(a) * (x .- a) .- sin(a) * (x .- a).^2 / 2, c=:red, l=:dash)
    xlims!(x[1], x[end])
    ylims!(-2, 2)
    frame(anim)
end
Plots.AnimatedGif("/home/runner/work/calculo-numerico/calculo-numerico/__site/assets/intro-a-julia/code/output/exemplo-4.gif")

Imagens 3d (ou de objetos 3d)

As principais ferramentas são o contour para curvas de nível e surface e wireframe para superfícies.

f(x,y) = x^2 + 4y^2
X = -1:0.05:1
Y = -1:0.05:1
layout = grid(2, 2)
plt = plot(layout = layout)
contour!(plt[1], X, Y, f)
surface!(plt[2], X, Y, f)
wireframe!(plt[3], X, Y, f)
surface!(plt[4], X, Y, f, camera=(60, 60))
f(x,y) = (y - 0.5) / (x^2 + 1)
layout = grid(2, 2)
plt = plot(layout = layout)
contour!(plt[1], X, Y, f)
surface!(plt[2], X, Y, f)
wireframe!(plt[3], X, Y, f)
surface!(plt[4], X, Y, f, camera=(60, 60))
u0(x, y) = exp(-((x - y^2)^2 + x^2))
X = -1.5:0.1:2.5
Y = -2:0.1:2
S = sum(u0.(X, Y)) * (X[2] - X[1]) * (Y[2] - Y[1])
u(t,x,y) = exp(-t) * (t * S + u0(x,y) * (1 - t))

t = 0:0.02:1
anim = Animation()
for ti = t
    layout = grid(2, 2)
    plt = plot(layout = layout)
    contour!(plt[1], X, Y, (x,y) -> u(ti,x,y))
    surface!(plt[2], X, Y, (x,y) -> u(ti,x,y))
    wireframe!(plt[3], X, Y, (x,y) -> u(ti,x,y))
    surface!(plt[4], X, Y, (x,y) -> u(ti,x,y), camera=(60, 60))
    zlims!(0, 1)
    frame(anim)
end
Plots.AnimatedGif("/home/runner/work/calculo-numerico/calculo-numerico/__site/assets/intro-a-julia/code/output/exemplo-5.gif")

Exercícios

  1. Crie um vetor x aleatório, e crie y = 2x + 3. Crie um plot e depois um scatter de x vs y.

  2. Faça o gráfico de e^x no intervalo [-1,1] em vermelho.

  3. Faça no mesmo gráfico os gráficos de 1, 1+x e 1+x+0.5x^2 em azul, com linha pontilhada.

x = rand(100)
y = 2x .+ 3
plot(x, y)
scatter!(x, y)
Plot{Plots.GRBackend() n=2}
plot(x -> exp(x), -1, 1, c=:red)
plot!(x -> 1, -1, 1, c=:blue, l=:dash)
plot!(x -> 1 + x, -1, 1, c=:blue, l=:dash)
plot!(x -> 1 + x + 0.5x^2, -1, 1, c=:blue, l=:dash)
Plot{Plots.GRBackend() n=4}