Come ogni altro programma:
La directory corrente:
Un consiglio:
È possibile interagire con il File System mediante comandi
Per visualizzare il percorso della directory corrente si usa:
pwd % sta per "Print Working Directory"
Per visualizzare il contenuto della directory corrente:
ls % sta per "list"
Per cambiare la directory corrente:
cd <percorso> % sta per Change Directory
Il percorso passato a cd
può essere assoluto o relativo
Per esempio, partendo da questo stato:
Con "cd esercitazione4
", otteniamo:
Il percorso passato a cd
può essere assoluto o relativo
Invece, partendo da questo stato:
Con "cd ..
", otteniamo:
Il percorso passato a cd
può essere assoluto o relativo
Ancora, partendo da questo stato:
Con "cd ../esercitazione5
", otteniamo:
Octave permette di leggere/scrivere dati su file
È un modo comodo per:
Ci focalizziamo sui file CSV (Comma Separated Values):
,
" (tipicamente Linux e Mac);
" (tipicamente Win e MS Excel)Un esempio di file CSV:
1; 2; 4; 8; 16; 32
1; 3; 9; 27; 81; 243
1; 4; 16; 64; 256; 1024
.csv
"Excel può:
;
";
"In Octave, i file CSV si leggono con:
csvread(<percorso file>);
dlmread(<percorso file>, <separatore>)
csvread
assume che il separatore sia ",
"dlmread
funziona qualunque sia il separatore<percorso file>
è il percorso (relativo o assoluto) del file
In Octave, i file CSV si leggono con:
csvwrite(<percorso file>, <dato>);
dlmwrite(<percorso file>, <dato>, <separatore>)
csvwrite
assume che il separatore sia ",
"dlmwrite
funziona qualunque sia il separatoreUn consiglio: utilizzare dlmread
/dlmwrite
Octave fornisce la funzione:
factorial(V)
Che restituisce un vettore con il fattoriale di ogni numero in V
V
devono essere numeri interin!
di un numero n
è definito come:n!={1 se n=0n∏i=1i se n>0
Si definisca una funzione:
XXX_factorial(V)
Che replichi tale comportamento
ch5_data2.csv
.m
<nome file> + [invio]
Una possibile soluzione:
function z = ch5_factorial(V)
z = [];
for ii = 1:length(V)
z(ii) = 1;
for jj = 1:V(ii)
z(ii) = z(ii) * jj;
end
end
end
Una possibile alternativa:
function z = ch5_factorial(V)
z = zeros(1, length(V));
for ii = 1:length(V)
z(ii) = prod(1:V(ii));
end
end
a:b
equivale a []
se a > b
prod([])
restituisce 1
Un possibile script di test:
% Carico i dati
V = dlmread('ch5_data2.csv');
% Calcolo i fattoriali
z1 = ch5_factorial(V);
% Ripeto l'operazione con la funzione di Octave
z2 = factorial(V);
% Verifico che il risultato sia corretto
all(z1 == z2)
Molte delle funzioni di Octave operano su vettori:
factorial
prende in ingresso un vettore.^
)Questo comportamento risulta comodo per disegnare
x = -5:0.1:5;
y = x.^2;
x
...x2i
per ogni elemento xi
A questo punto, si può disegnare la funzione con:
plot(x, y);
La funzione plot
produce un grafico a linee
Si può decidere il formato della linea con:
plot(x, y, fmt);
Dove fmt
è una stringa che decide il formato:
fmt
è 'b'
la linea è blu, se fmt
è 'r'
è rossahelp
o doc
)Si può disegnare più di una funzione con la sintassi:
plot(x1, y1, fmt1, x2, y2, fmt2, ...);
Per esempio, potete disegnare sia x2
che x3
con:
x = -5:.1:5;
plot(x, x.^2, 'b', x, x.^3, 'r')
x2
sarà blux3
sarà rossaOctave permette di valutare un polinomio con:
polyval(p, X)
Dove:
X
contiene i valori per cui fare la valutazionep
è un vettore di n
coefficienti che definiscono il polinomio:p1xn−1+p2xn−2+…+pn
Per esempio polyval([3, 0, 4], 2)
restituisce:
3×22+0×21+4=16
Si definisca una funzione:
XXX_polyval(X)
Che replichi tale comportamento
X
sia uno scalare...Per verificare che tutto funzioni:
XXX_polyval
e con polyval
Una possibile soluzione:
function z = ch5_polyval(p, X)
z = 0;
for ii = 1:length(p)
z = z + p(ii) .* X.^(length(p)-ii);
end
end
Idea generale: elevo ad esponente tutte le X
e sommo
X
scalare che per X
vettore...+
, .*
e .^
operano elemento per elementoUna soluzione alternativa:
function z = ch5_polyval(p, X)
n = length(p)-1:-1:0; % esponenti
z = [];
for ii = 1:length(X)
z(ii) = dot(p, X(ii).^n); % prodotto scalare
end
end
Idea generale: elevo ciascuna X
a tutti gli esponenti e sommo
Un possibile script di test:
% Definisco un polinomio
p = [1, 3, -2, -1, 7];
% Definisco i valori per cui va calcolato
X = -5:.1:5;
% Valuto il polinomio utilizzando i due metodi
Z0 = ch5_polyval(p, X);
Z1 = polyval(p, X);
% Disegno le due curve
plot(X, Z0, 'b', X, Z1, 'r')
Data una funzione f
ed un punto x0
, la serie di Taylor:
f(x)=f(x0)+f′(x0)1!(x−x0)+f″
In forma compatta:
f(x) = \sum_{i = 0}^{\infty} \frac{f^{(i)}}{i!} (x-x_0)^i
f
deve essere infinitamente differenziabile in x_0
Considerando solo n
termini:
f
in ogni puntox_0
:f(x_0)
x_0
Un caso facile: e^x
x_0 = 0
, la funzione e^x
vale 1
...e^x
valgono 1
Si definisca una funzione:
XXX_taylor_exp(X, n)
Che approssimi e^x
utilizzando la serie di Taylor per x_0 = 0
:
n
termini della seriex_i
nel vettore X
Per verificare se funziona:
e^x
per un certo rangen
)Una possibile soluzione:
function z = ch5_taylor_exp(x, n)
z = 1; % termine di ordine 0
for ii = 1:n
% calcolo il coefficiente del polinomio
% di Taylor di ordine ii
c = 1 / factorial(ii);
% sommo un termine del polinimio
z = z + c .* x.^ii;
end
end
Una alternativa:
function z = ch5_taylor_exp(x, n)
% Calcolo i coefficienti del polinomio di Taylor
c = 1./factorial(n:-1:0);
% Valuto il polinomio
z = polyval(c, x);
end
Un possibile script di test:
n = 5; % Decido il valore di n
x = 0:.2:4; % Il range per il disegno
z1 = e.^x; % I valori di e^x
% Calcolo l'approssimazione
z2 = ch5_taylor_exp(x, n);
% Disegno le due curve
plot(x, z1, 'b', x, z2, 'r');
Per ottenere la rappresentazione binaria di un intero n
si usa:
dec2bin(n)
n
non ha parte frazionariaSi definisca una funzione:
XXX_dec2bin(n)
Alcune informazioni utili:
idivide(<dividendo>, <divisore>)
mod(<dividendo>, <divisore>)
Una possibile soluzione:
function z = ch5_dec2bin(n)
z = [];
ii = 1;
while n > 0
z(ii) = mod(n, 2);
n = idivide(n, 2);
ii = ii + 1;
end
% Inverto la sequenza dei bit
z = z(end:-1:1);
end
Si definisca una funzione:
XXX_dec2bin_f(x)
Che, dato un numero reale x
in ]0, 1[
10^a
cifra binariaSi noti che non è necessario rappresentare il separatore ".
"
fix(<dato>)
Una possibile soluzione:
function z = ch5_dec2bin_f(n)
z = [];
for ii = 1:10
y = n * 2;
z(ii) = fix(y);
n = y - z(ii);
end
end
Si definisca una funzione:
XXX_msum(A, B)
Che calcoli a somma di due matrici
+
applicato a vettoriUna possibile soluzione:
function Z = ch4_msum(A, B)
m = rows(A);
n = columns(A);
Z = zeros(m, n);
for ii = 1:m
for jj = 1:n
Z(ii, jj) = A(ii,jj) + B(ii,jj);
end
end
end
Si definisca una funzione:
XXX_transpose(A)
Che calcoli la trasposizione della matrice A
Una possibile soluzione:
function Z = ch4_msum(A)
m = rows(A);
n = columns(A);
Z = zeros(n, m);
for ii = 1:m
for jj = 1:n
Z(jj, ii) = A(ii,jj);
end
end
end
Si definisca una funzione:
XXX_mprod(A, B)
Che calcoli il prodotto matriciale di A
e B
Una possibile soluzione:
function Z = ch4_mprod(A, B)
m = rows(A);
n = columns(B);
Z = zeros(m, n);
for ii = 1:m
for jj = 1:n
% Qui potrei usare anche "dot"
Z(ii,jj) = A(ii,:) * B(:, jj);
end
end
end
Si definisca una funzione:
[U, C] = XXX_count(V)
Che, dato un vettore di ingresso V
, restituisca U
e C
tali che:
U
contenga gli elementi distinti di V
v
in U
, C
contenga il numero di occorrenze di v
in U
In altre parole, la funzione deve contare le occorrenze di ogni elemento.
ch5_data1.csv
ch5_count_u.csv
e ch5_count_c.csv
Una possibile soluzione:
function [U, C] = ch5_count(V)
U = unique(V);
C = zeros(1, length(U));
for ii = 1:length(U)
for jj = 1:length(V)
if V(jj) == U(ii)
C(ii) = C(ii) + 1;
end
end
end
end
Una alternativa:
function [U, C] = ch5_count(V)
U = unique(V);
C = zeros(1, length(U));
for ii = 1:length(U)
C(ii) = sum(V == U(ii));
end
end
Un possibile script di test:
% Carico i dati
V = dlmread('ch5_data1.csv');
% Ottengo gli elementi unici ed i conteggi
[U, C] = ch5_count(V);
% Carico le soluzioni
U2 = dlmread('ch5_count_u.csv');
C2 = dlmread('ch5_count_c.csv');
% Controllo che i risultati siano corretti
all(U == U2)
all(C == C2)
Si definisca una funzione:
XXX_serie_fatt(n)
Che calcoli per un ordine n
il valore della serie:
\sum_{i = 1}^n i!
Si provi a definire la funzione utilizzando:
Una possibile soluzione con cicli innestati:
function z = ch5_serie_fatt(n)
z = 0;
for ii = 1:n
% calcolo il fattoriale di ii
fatt = 1;
for jj = 1:ii
fatt = fatt * jj;
end
% sommo il fattoriale
z = z + fatt;
end
end
Una possibile soluzione con un solo ciclo:
function z = ch5_serie_fatt(n)
z = 0;
for ii = 1:n
% calcolo il fattoriale di ii
fatt = prod(1:ii); % oppure factorial(ii);
% sommo il fattoriale
z = z + fatt;
end
end
Un'altra possibile soluzione con un solo ciclo:
function z = ch5_serie_fatt(n)
z = 0;
fatt = 1;
for ii = 1:n
% aggiorno il fattoriale di ii
fatt = fatt * ii;
% sommo il fattoriale
z = z + fatt;
end
end
Una soluzione senza cicli
function z = ch5_serie_fatt(n)
z = sum(factorial(1:n));
end
sum
e factorial
La derivata di un polinomio:
p_1 x^{n-1} + p_2 x^{n-2} + \ldots + p_n
È un polinomio:
(n-1) p_1 x^{n-2} + (n-2) p_2 x^{n-3} + \ldots + p_{n-1}
Octave permette di calcolarlo utilizzando:
polyder(p)
XXX_polyder(p)
...Una possibile soluzione:
function p2 = ch4_polyder(p)
n = length(p)-1; % ordine del polinomio
% Coefficienti dovuti alla derivazione dei monomi
ce = n:-1:1;
% Primi n coefficienti del polinomio originale
cp = p(1:n);
% Faccio il prodotto ed ottengo la derivata
p2 = ce .* cp;
end
L'integrale di un polinomio:
p_1 x^{n-1} + p_2 x^{n-2} + \ldots + p_n
È un polinomio:
\frac{1}{n} p_1 x^{n} + \frac{1}{n-1} p_2 x^{n-1} + \ldots + p_n x
Octave permette di calcolarlo utilizzando:
polyint(p)
XXX_polyint(p)
...Una possibile soluzione:
function p2 = ch4_polyint(p)
n = length(p)-1; % ordine del polinomio
% Coefficienti dovuti all'integrazione dei monomi
ce = 1 ./ (n+1:-1:1);
% Integrale per i primi n termini del polinomio
p2 = ce .* p;
% Estendo il polinomio risultato con uno 0
p2(end+1) = 0;
end
Si può ottenere una permutazione dei numeri da 1
a n
con:
randperm(n)
Esempio:
v = [2, 4, 6, 8];
p = randperm(length(v)) % denota (e.g.) [2, 4, 1, 3]
w = v(p) % [4, 8, 2, 6]
Si definisca una funzione:
XXX_invperm(v1, v2)
Che, dati due vettori contenenti gli stessi elementi in ordine diverso:
w
tale che...w
contiene le posizioni in v2
degli elementi di v1
v2
è una sorta di permuazione inversa:
p
abbiamo che v1(p) == v2
...p2 = XXX_invperm(v1, v2)
v2(p2) == v1
Una possibile zSoluzione:
function p = ch4_invperm(v1, v2)
n = length(v1);
p = zeros(1, n);
for ii = 1:n
for jj = 1:n
if v1(ii) == v2(jj)
p(ii) = jj;
break; % interrompe il ciclo su jj
end
end
end
end
Una possibile alternativa:
function p = ch4_invperm(v1, v2)
n = length(v1);
p = zeros(1, n);
for ii = 1:n
p(ii) = find(v2 == v1(ii));
end
end
Un possibile script di test:
v1 = [4, 7, 9, 1, 5] % costruisco un vettore
p = randperm(length(v1)) % permutazione casuale
v2 = v1(p) % "Mescolo" v1
% Calcolo la permutazione inversa
p2 = ch4_invperm(v1, v2)
% stampo il risultato dell'indicizzazione con p2.
% Deve essere uguale a v1
v2(p2)