MATLAB Language - RIP Tutorialfrom: matlab-language It is an unofficial and free MATLAB Language...
Transcript of MATLAB Language - RIP Tutorialfrom: matlab-language It is an unofficial and free MATLAB Language...
MATLAB Language
#matlab
Sommario
Di 1
Capitolo 1: Iniziare con MATLAB Language 2
Versioni 2
Vedi anche: storia del rilascio di MATLAB su Wikipedia . 3
Examples 3
Ciao mondo 4
Matrici e matrici 4
Matrici e matrici di indicizzazione 6
Indicizzazione degli indici 6
Indicizzazione lineare 7
Indicizzazione logica 9
Maggiori informazioni sull'indicizzazione 10
Aiutare te stesso 12
Lettura di input e scrittura 13
Matrici cellulari 14
Script e funzioni 15
Tipi di dati 17
Funzioni anonime e maniglie di funzione 20
Nozioni di base 20
L'operatore @ 20
Funzioni anonime personalizzate 21
Funzioni anonime di una variabile 21
Funzioni anonime di più di una variabile 21
Parametrizzare le funzioni anonime 21
Gli argomenti di input per una funzione anonima non si riferiscono alle variabili di works 22
Le funzioni anonime sono memorizzate in variabili 22
Uso avanzato 23
Passaggio delle funzioni alle altre funzioni 23
Utilizzo di bsxfun , cellfun e funzioni simili con funzioni anonime 23
Capitolo 2: Applicazioni finanziarie 25
Examples 25
Camminata casuale 25
Moto mariano geometrico univariato 25
Capitolo 3: Best practice di MATLAB 28
Osservazioni 28
Examples 28
Mantenere le linee brevi 28
Codice di rientro correttamente 28
Usa assert 29
Evitare i loop 30
Esempi 30
Crea un nome univoco per il file temporaneo 30
Utilizzare validateattributes 32
Block Comment Operator 37
Capitolo 4: condizioni 39
Sintassi 39
Parametri 39
Examples 39
Condizione IF 39
Condizione IF-ELSE 40
Condizione IF-ELSEIF 40
Condizioni nidificate 42
Capitolo 5: Controllo della colorazione di sottotrama in Matlab 44
introduzione 44
Osservazioni 44
Examples 44
Come è fatto 44
Capitolo 6: Debug 46
Sintassi 46
Parametri 46
Examples 46
Lavorare con i punti di interruzione 46
Definizione 46
Punti di interruzione in MATLAB 46
Motivazione 47
Tipi di punti di interruzione 47
Posizionamento dei punti di interruzione 47
Disabilitare e riattivare i punti di interruzione 48
Rimozione dei punti di interruzione 48
Ripresa dell'esecuzione 48
Debug di codice Java richiamato da MATLAB 49
Panoramica 49
Fine MATLAB 49
Finestre: 49
Fine del debugger 50
IntelliJ IDEA 50
Capitolo 7: Disegno 53
Examples 53
Circles 53
frecce 55
Ellisse 58
Poligono (s) 59
Singolo poligono 59
Poligoni multipli 60
Trama Pseudo 4D 60
Disegno veloce 65
Capitolo 8: Elaborazione delle immagini 67
Examples 67
Immagine di base I / O 67
Recupera le immagini da Internet 67
Filtro usando un FFT 2D 67
Filtro delle immagini 68
Proprietà di misurazione delle regioni collegate 70
Capitolo 9: Errori e errori comuni 73
Examples 73
Non nominare una variabile con un nome di funzione esistente 73
Quello che vedi NON è quello che ottieni: char vs cellstring nella finestra di comando 73
Gli operatori di trasposizione 74
Funzione non definita o metodo X per gli argomenti di input di tipo Y 75
Quella funzione è stata introdotta dopo la tua attuale versione di MATLAB 75
Non hai quella cassetta degli attrezzi! 76
MATLAB non può localizzare la funzione 77
Siate consapevoli di inesattezze in virgola mobile 77
Esempi: confronto in virgola mobile eseguito ERRATO: 77
Esempio: confronto a virgola mobile fatto a DESTRA: 78
Ulteriori letture: 78
Argomenti di input insufficienti 78
Metodo n. 1 - Tramite il prompt dei comandi 79
Metodo n. 2: interattivo attraverso l'editor 79
Fai attenzione alle modifiche alle dimensioni degli array 80
Errori di mancata corrispondenza delle dimensioni 81
L'uso di "i" o "j" come unità immaginaria, indici di loop o variabile comune. 81
Raccomandazione 81
Predefinito 81
Usarli come variabile (per indici di loop o altre variabili) 82
Usandoli come unità immaginaria: 83
insidie 83
Usando `length` per gli array multidimensionali 84
Capitolo 10: Funzionalità non documentate 85
Osservazioni 85
Examples 85
Funzioni di supporto compatibili con C ++ 85
Tracciati 2D con codice colore con dati colore in terza dimensione 85
Marcatori semi-trasparenti in linea e grafici a dispersione 86
Profili di contorno: personalizza le etichette di testo 88
Aggiunta / aggiunta di voci a una legenda esistente 89
Dispersione della trama dispersa 90
Capitolo 11: funzioni 92
Examples 92
Esempio di base 92
Uscite multiple 92
nargin, nargout 93
Capitolo 12: Funzioni di documentazione 95
Osservazioni 95
Examples 95
Documentazione di funzioni semplici 95
Documentazione delle funzioni locali 95
Ottenere una firma di funzione 96
Documentare una funzione con uno script di esempio 96
Capitolo 13: Grafica: grafici a linee 2D 100
Sintassi 100
Parametri 100
Osservazioni 100
Examples 100
Più linee in un singolo grafico 100
Linea divisa con NaNs 101
Ordini personalizzati di colori e linee 102
Capitolo 14: Grafica: trasformazioni 2D e 3D 106
Examples 106
Trasformazioni 2D 106
Capitolo 15: Imposta le operazioni 109
Sintassi 109
Parametri 109
Examples 109
Operazioni di set elementare 109
Capitolo 16: Inizializzazione di matrici o array 111
introduzione 111
Sintassi 111
Parametri 111
Osservazioni 111
Examples 111
Creazione di una matrice di 0s 111
Creazione di una matrice di 1 s 112
Creare una matrice di identità 112
Capitolo 17: Integrazione 113
Examples 113
Integrale, integrale2, integrale3 113
Capitolo 18: Interfacce utente MATLAB 115
Examples 115
Passaggio dei dati intorno all'interfaccia utente 115
guidata 115
setappdata / getappdata 115
UserData 116
Funzioni annidate 117
Argomenti di input espliciti 117
Creazione di un pulsante nell'interfaccia utente che sospende l'esecuzione di callback 118
Trasmettere dati in giro usando la struttura "maniglie" 119
Problemi di prestazioni quando si passano dati intorno all'interfaccia utente 120
Capitolo 19: Interpolazione con MATLAB 123
Sintassi 123
Examples 123
Interpolazione a tratti 2 dimensionale 123
Interpolazione a tratti 1 dimensionale 126
Interpolazione polinomiale 132
Capitolo 20: Introduzione all'API MEX 136
Examples 136
Controllare il numero di ingressi / uscite in un file MEX C ++ 136
testinputs.cpp 136
Inserisci una stringa, modificala in C e stampala 137
stringIO.cpp 137
Passa una matrice 3D da MATLAB a C 138
matrixIn.cpp 138
Passare una struttura per nome di campo 140
structIn.c 140
Capitolo 21: Lettura di file di grandi dimensioni 141
Examples 141
textSCAN 141
Le stringhe della data e dell'ora sull'array numerico sono veloci 141
Capitolo 22: multithreading 143
Examples 143
Usare parfor per parallelizzare un loop 143
Quando usare parfor 143
Esecuzione di comandi in parallelo usando un'istruzione "Single Program, Multiple Data" (S 144
Utilizzo del comando batch per eseguire vari calcoli in parallelo 145
Capitolo 23: Per i loop 146
Osservazioni 146
Iterare sul vettore di colonna 146
Modifica della variabile di iterazione 146
Prestazione speciale di a:b caso a:b nella parte destra 146
Examples 147
Passare da 1 a n 147
Iterare su elementi del vettore 147
Iterare su colonne di matrice 149
Loop over indexes 149
Cicli annidati 149
Avviso: strani loop con lo stesso contatore. 151
Capitolo 24: Prestazioni e Benchmarking 152
Osservazioni 152
Examples 152
Identificazione dei colli di bottiglia delle prestazioni utilizzando il Profiler 152
Confronto del tempo di esecuzione di più funzioni 155
Va bene essere "single"! 156
Panoramica: 156
Conversione di variabili in uno script in una precisione / tipo / classe non predefinita: 157
Avvertenze e insidie: 157
Guarda anche: 158
riorganizzare un array ND può migliorare le prestazioni generali 158
L'importanza della preallocazione 160
Capitolo 25: Programmazione orientata agli oggetti 163
Examples 163
Definire una classe 163
Classe di esempio: 163
Classi Value vs Handle 164
Ereditando da classi e classi astratte 165
Costruttori 169
Capitolo 26: Risolutori di equazioni differenziali ordinarie (ODE) 172
Examples 172
Esempio per odeset 172
Capitolo 27: Scomposizioni della matrice 174
Sintassi 174
Examples 174
Scomposizione di Cholesky 174
Decomposizione QR 174
Decomposizione LU 175
Scomposizione di Schur 176
Scomposizione di un valore singolo 177
Capitolo 28: Trasformate di Fourier e Trasformate di Fourier inverse 178
Sintassi 178
Parametri 178
Osservazioni 179
Examples 179
Implementa una semplice trasformazione di Fourier in Matlab 179
Trasformate di Fourier inverse 180
Immagini e FT multidimensionali 182
Riempimento a zero 182
Suggerimenti, consigli, 3D e oltre 186
Capitolo 29: Trucchi utili 188
Examples 188
Funzioni utili che operano su celle e array 188
Preferenze di piegatura del codice 190
Estrai dati figure 193
Programmazione funzionale usando le funzioni anonime 194
Salva più figure nello stesso file .fig 195
Blocchi di commento 195
Capitolo 30: Usando le porte seriali 197
introduzione 197
Parametri 197
Examples 197
Creazione di una porta seriale su Mac / Linux / Windows 198
Lettura dalla porta seriale 198
Chiusura di una porta seriale anche se persa, cancellata o sovrascritta 198
Scrivere sulla porta seriale 198
Scegli la tua modalità di comunicazione 199
Modalità 1: sincrono (master / slave) 199
Modalità 2: asincrona 200
Modalità 3: streaming ( tempo reale ) 201
Elaborazione automatica dei dati ricevuti da una porta seriale 202
Capitolo 31: Utility di programmazione 204
Examples 204
Semplice timer in MATLAB 204
Capitolo 32: Utilizzo della funzione `accumarray ()` 205
introduzione 205
Sintassi 205
Parametri 205
Osservazioni 205
Riferimenti : 206
Examples 206
Trovare il valore massimo tra gli elementi raggruppati da un altro vettore 206
Applica il filtro alle patch delle immagini e imposta ciascun pixel come media del risulta 206
Capitolo 33: Utilizzo di funzioni con output logico 208
Examples 208
Tutti e Tutti con array vuoti 208
Capitolo 34: vettorializzazione 209
Examples 209
Operazioni elementali 209
Somma, significa, prod & co 209
Uso di bsxfun 210
Sintassi 211
Osservazioni 212
Mascheramento logico 212
Espansione di array implicita (broadcasting) [R2016b] 213
Esempi di dimensioni compatibili: 214
Esempi di dimensioni incompatibili: 214
Ottieni il valore di una funzione di due o più argomenti 215
Titoli di coda 217
Di
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: matlab-language
It is an unofficial and free MATLAB Language ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official MATLAB Language.
The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/it/home 1
Capitolo 1: Iniziare con MATLAB Language
Versioni
Versione pubblicazione Data di rilascio
1.0 1984-01-01
2 1986-01-01
3 1987-01-01
3.5 1990-01-01
4 1992/01/01
4.2c 1994-01-01
5.0 Volume 8 1996/12/01
5.1 Volume 9 1997/05/01
5.1.1 R9.1 1997/05/02
5.2 R10 1998/03/01
5.2.1 R10.1 1998/03/02
5.3 R11 1999-01-01
5.3.1 r11.1 1999/11/01
6.0 R12 2000/11/01
6.1 r12.1 2001-06-01
6.5 R13 2002-06-01
6.5.1 R13SP2 2003-01-01
6.5.2 R13SP2 2003-01-02
7 R14 2006-06-01
7.0.4 R14SP1 2004-10-01
7.1 R14SP3 2005-08-01
7.2 R2006a 2006-03-01
https://riptutorial.com/it/home 2
Versione pubblicazione Data di rilascio
7.3 R2006b 2006-09-01
7.4 R2007a 2007-03-01
7.5 R2007b 2007-09-01
7.6 R2008a 2008-03-01
7.7 R2008b 2008-09-01
7.8 R2009a 2009-03-01
7.9 R2009b 2009-09-01
7.10 R2010a 2010-03-01
7.11 R2010b 2010-09-01
7.12 R2011a 2011-03-01
7.13 R2011b 2011-09-01
7.14 R2012a 2012-03-01
8.0 R2012b 2012-09-01
8.1 R2013a 2013/03/01
8.2 R2013b 2013/09/01
8.3 R2014a 2014/03/01
8.4 R2014b 2014/09/01
8.5 R2015a 2015/03/01
8.6 R2015b 2015/09/01
9.0 R2016a 2016/03/01
9.1 R2016b 2016/09/14
9.2 R2017a 2017/03/08
Vedi anche: storia del rilascio di MATLAB su Wikipedia .
Examples
https://riptutorial.com/it/home 3
Ciao mondo
Apri un nuovo documento vuoto nell'editor MATLAB (nelle versioni recenti di MATLAB, fai questo selezionando la scheda Home della barra degli strumenti e facendo clic su Nuovo script). La scorciatoia da tastiera predefinita per creare un nuovo script è Ctrl-n .
In alternativa, digitando edit myscriptname.m si aprirà il file myscriptname.m per la modifica o si offrirà di creare il file se non esiste sul percorso MATLAB.
Nell'editor, digitare quanto segue:
disp('Hello, World!');
Seleziona la scheda Editor della barra degli strumenti e fai clic su Salva come. Salva il documento in un file nella directory corrente chiamato helloworld.m . Salvando un file senza titolo verrà visualizzata una finestra di dialogo per denominare il file.
Nella finestra di comando MATLAB, digitare quanto segue:
>> helloworld
Dovresti vedere la seguente risposta nella finestra di comando MATLAB:
Hello, World!
Vediamo che nella finestra di comando, siamo in grado di digitare i nomi delle funzioni o dei file di script che abbiamo scritto, o che sono forniti con MATLAB, per eseguirli.
Qui, abbiamo eseguito lo script 'helloworld'. Si noti che la digitazione dell'estensione ( .m ) non è necessaria. Le istruzioni contenute nel file di script sono eseguite da MATLAB, qui viene stampato 'Hello, World!' usando la funzione disp .
I file di script possono essere scritti in questo modo per salvare una serie di comandi da riutilizzare in seguito.
Matrici e matrici
In MATLAB, il tipo di dati più semplice è l'array numerico. Può essere uno scalare, un vettore 1-D, una matrice 2-D o un array multidimensionale ND.
% a 1-by-1 scalar value x = 1;
Per creare un vettore riga, inserisci gli elementi tra parentesi, separati da spazi o virgole:
% a 1-by-4 row vector v = [1, 2, 3, 4]; v = [1 2 3 4];
https://riptutorial.com/it/home 4
Per creare un vettore colonna, separa gli elementi con punto e virgola:
% a 4-by-1 column vector v = [1; 2; 3; 4];
Per creare una matrice, inseriamo le righe come prima separate da punto e virgola:
% a 2 row-by-4 column matrix M = [1 2 3 4; 5 6 7 8]; % a 4 row-by-2 column matrix M = [1 2; ... 4 5; ... 6 7; ... 8 9];
Si noti che non è possibile creare una matrice con dimensioni di riga / colonna non uguali. Tutte le righe devono avere la stessa lunghezza e tutte le colonne devono avere la stessa lunghezza:
% an unequal row / column matrix M = [1 2 3 ; 4 5 6 7]; % This is not valid and will return an error % another unequal row / column matrix M = [1 2 3; ... 4 5; ... 6 7 8; ... 9 10]; % This is not valid and will return an error
Per trasporre un vettore o una matrice, usiamo il .' -operatore, o ' operatore a prendere il suo coniugato ermetico, che è il complesso coniugato della sua trasposizione. Per le matrici reali, questi due sono gli stessi:
% create a row vector and transpose it into a column vector v = [1 2 3 4].'; % v is equal to [1; 2; 3; 4]; % create a 2-by-4 matrix and transpose it to get a 4-by-2 matrix M = [1 2 3 4; 5 6 7 8].'; % M is equal to [1 5; 2 6; 3 7; 4 8] % transpose a vector or matrix stored as a variable A = [1 2; 3 4]; B = A.'; % B is equal to [1 3; 2 4]
Per matrici di più di due dimensioni, non esiste una sintassi di linguaggio diretta per inserirle letteralmente. Invece dobbiamo usare le funzioni per costruirle (come ones , zeros , rand ) o manipolando altri array (usando funzioni come cat , reshape , permute ). Qualche esempio:
% a 5-by-2-by-4-by-3 array (4-dimensions) arr = ones(5, 2, 4, 3); % a 2-by-3-by-2 array (3-dimensions) arr = cat(3, [1 2 3; 4 5 6], [7 8 9; 0 1 2]); % a 5-by-4-by-3-by-2 (4-dimensions) arr = reshape(1:120, [5 4 3 2]);
https://riptutorial.com/it/home 5
Matrici e matrici di indicizzazione
MATLAB consente diversi metodi per indicizzare (accedere) elementi di matrici e matrici:
Indicizzazione del pedice - dove si specifica la posizione degli elementi che si desidera in ciascuna dimensione della matrice separatamente.
•
Indicizzazione lineare - in cui la matrice viene trattata come un vettore, indipendentemente dalle sue dimensioni. Ciò significa che si specifica ciascuna posizione nella matrice con un singolo numero.
•
Indicizzazione logica : in cui si utilizza una matrice logica (e una matrice di valori true e false ) con le dimensioni identiche della matrice che si tenta di indicizzare come maschera per specificare quale valore restituire.
•
Questi tre metodi sono ora spiegati in maggior dettaglio usando la seguente matrice 3 per 3 M come esempio:
>> M = magic(3) ans = 8 1 6 3 5 7 4 9 2
Indicizzazione degli indici
Il metodo più diretto per accedere a un elemento consiste nel specificare il suo indice di riga-colonna. Ad esempio, accedendo all'elemento sulla seconda riga e sulla terza colonna:
>> M(2, 3) ans = 7
Il numero di pedici forniti corrisponde esattamente al numero di dimensioni che M ha (due in questo esempio).
Si noti che l'ordine degli indici è lo stesso della convenzione matematica: l'indice di riga è il primo. Inoltre, gli indici MATLAB iniziano con 1 e non 0 come la maggior parte dei linguaggi di programmazione.
È possibile indicizzare più elementi contemporaneamente passando un vettore per ogni coordinata anziché un singolo numero. Ad esempio per ottenere l'intera seconda riga, possiamo specificare che vogliamo la prima, la seconda e la terza colonna:
>> M(2, [1,2,3]) ans =
https://riptutorial.com/it/home 6
3 5 7
In MATLAB, il vettore [1,2,3] è più facilmente creato usando l'operatore colon, ovvero 1:3 . Puoi usare questo anche nell'indicizzazione. Per selezionare un'intera riga (o colonna), MATLAB fornisce una scorciatoia consentendo semplicemente di specificare : Ad esempio, il codice seguente restituirà anche l'intera seconda riga
>> M(2, :) ans = 3 5 7
MATLAB fornisce anche una scorciatoia per specificare l'ultimo elemento di una dimensione nella forma della parola chiave di end . La parola chiave end funzionerà esattamente come se fosse il numero dell'ultimo elemento in quella dimensione. Quindi se vuoi che tutte le colonne dalla colonna 2 all'ultima colonna, puoi usare scrivi quanto segue:
>> M(2, 2:end) ans = 5 7
L'indicizzazione del pedice può essere restrittiva in quanto non consente di estrarre singoli valori da diverse colonne e righe; estrarrà la combinazione di tutte le righe e colonne.
>> M([2,3], [1,3]) ans = 3 7 4 2
Ad esempio, l'indicizzazione del pedice non può estrarre solo gli elementi M(2,1) o M(3,3) . Per fare ciò, dobbiamo considerare l'indicizzazione lineare.
Indicizzazione lineare
MATLAB consente di trattare gli array n-dimensionali come matrici unidimensionali quando si indice utilizzando solo una dimensione. Puoi accedere direttamente al primo elemento:
>> M(1) ans = 8
Nota che gli array sono memorizzati nell'ordine delle colonne in MATLAB, il che significa che accederai agli elementi facendo prima scendere le colonne. Quindi M(2) è il secondo elemento della prima colonna che è 3 e M(4) sarà il primo elemento della seconda colonna cioè
https://riptutorial.com/it/home 7
>> M(4) ans = 1
Esistono funzioni incorporate in MATLAB per convertire gli indici degli indici in indici lineari e viceversa: sub2ind e ind2sub rispettivamente. Puoi convertire manualmente i pedici ( r , c ) in un indice lineare di
idx = r + (c-1)*size(M,1)
Per capire questo, se siamo nella prima colonna, l'indice lineare sarà semplicemente l'indice di riga. La formula sopra riportata vale per questo perché per c == 1 , (c-1) == 0 . Nelle colonne successive, l'indice lineare è il numero di riga più tutte le righe delle colonne precedenti.
Si noti che la parola chiave di end si applica ancora e ora si riferisce all'ultimo elemento della matrice cioè M(end) == M(end, end) == 2 .
Puoi anche indicizzare più elementi usando l'indicizzazione lineare. Nota che se lo fai, la matrice restituita avrà la stessa forma della matrice dei vettori di indice.
M(2:4) restituisce un vettore di riga perché 2:4 rappresenta il vettore di riga [2,3,4] :
>> M(2:4) ans = 3 4 1
Come altro esempio, M([1,2;3,4]) restituisce una matrice 2 per 2 perché [1,2;3,4] è anche una matrice 2 per 2. Vedi il codice qui sotto per convincerti:
>> M([1,2;3,4]) ans = 8 3 4 1
Si noti che l'indicizzazione con : da sola restituirà sempre un vettore di colonna:
>> M(:) ans = 8 3 4 1 5 9 6
https://riptutorial.com/it/home 8
7 2
Questo esempio illustra anche l'ordine in cui MATLAB restituisce elementi quando si utilizza l'indicizzazione lineare.
Indicizzazione logica
Il terzo metodo di indicizzazione consiste nell'utilizzare una matrice logica, ovvero una matrice contenente solo valori true o false , come maschera per filtrare gli elementi che non si desidera. Ad esempio, se vogliamo trovare tutti gli elementi di M maggiori di 5 , possiamo usare la matrice logica
>> M > 5 ans = 1 0 1 0 0 1 0 1 0
per indicizzare M e restituire solo i valori superiori a 5 come segue:
>> M(M > 5) ans = 8 9 6 7
Se si desidera che questi numeri rimangano in posizione (ovvero mantengano la forma della matrice), è possibile assegnare il complimento logico
>> M(~(M > 5)) = NaN ans = 8 NaN 6 NaN NaN 7 NaN 9 Nan
Possiamo ridurre complicati blocchi di codice contenenti if e for istruzioni utilizzando l'indicizzazione logica.
Prendi il non vettorizzato (già abbreviato in un singolo ciclo usando l'indicizzazione lineare):
for elem = 1:numel(M) if M(elem) > 5 M(elem) = M(elem) - 2; end
https://riptutorial.com/it/home 9
end
Questo può essere abbreviato con il seguente codice usando l'indicizzazione logica:
idx = M > 5; M(idx) = M(idx) - 2;
O ancora più corto:
M(M > 5) = M(M > 5) - 2;
Maggiori informazioni sull'indicizzazione
Matrici di dimensione superiore
Tutti i metodi sopra menzionati si generalizzano in n-dimensioni. Se usiamo la matrice tridimensionale M3 = rand(3,3,3) come esempio, allora puoi accedere a tutte le righe e le colonne della seconda porzione della terza dimensione scrivendo
>> M(:,:,2)
È possibile accedere al primo elemento della seconda sezione utilizzando l'indicizzazione lineare. L'indicizzazione lineare passerà alla seconda sezione solo dopo tutte le righe e tutte le colonne della prima sezione. Quindi l'indice lineare per quell'elemento è
>> M(size(M,1)*size(M,2)+1)
Infatti, in MATLAB, ogni matrice è n-dimensionale: è solo che le dimensioni della maggior parte delle altre n-dimensioni sono una. Quindi, se a = 2 allora a(1) == 2 (come ci si aspetterebbe), ma anche a(1, 1) == 2 , così come a(1, 1, 1) == 2 , a(1, 1, 1, ..., 1) == 2 e così via. Queste dimensioni "extra" (di dimensione 1 ), sono indicate come dimensioni singleton . Il comando squeeze li rimuoverà e uno può usare permute per scambiare l'ordine delle dimensioni intorno (e introdurre le dimensioni singleton se necessario).
Una matrice n-dimensionale può anche essere indicizzata usando m subscripts (dove m <= n). La regola è che i primi indici m-1 si comportano normalmente, mentre l'ultimo (m'th) indice fa riferimento alle restanti dimensioni (n-m + 1), proprio come un indice lineare farebbe riferimento a un (n-m + 1) dimensionale array. Ecco un esempio:
>> M = reshape(1:24,[2,3,4]); >> M(1,1) ans = 1 >> M(1,10) ans = 19 >> M(:,:) ans = 1 3 5 7 9 11 13 15 17 19 21 23
https://riptutorial.com/it/home 10
2 4 6 8 10 12 14 16 18 20 22 24
Restituire intervalli di elementi
Con l'indicizzazione del pedice, se si specifica più di un elemento in più di una dimensione, MATLAB restituisce ciascuna coppia possibile di coordinate. Ad esempio, se provi M ([1,2], [1,3]) MATLAB restituirà M(1,1) e M(2,3) ma restituirà anche M(1,3) e M(2,1) . Questo può sembrare non intuitivo quando si cercano gli elementi per un elenco di coppie di coordinate, ma si consideri l'esempio di una matrice più grande, A = rand(20) (la nota A è ora 20 -by- 20 ), dove si desidera ottenere il quadrante in alto a destra. In questo caso invece di dover specificare ogni coppia di coordinate in quel quadrante (e questo in questo caso sarebbe 100 coppie), devi solo specificare le 10 righe e le 10 colonne che vuoi così A(1:10, 11:end) . Affettare una matrice come questa è molto più comune che richiedere un elenco di coppie di coordinate.
Nel caso in cui si desideri ottenere un elenco di coppie di coordinate, la soluzione più semplice è quella di convertire in indicizzazione lineare. Si consideri il problema in cui si ha un vettore di indici di colonna che si desidera restituire, in cui ogni riga del vettore contiene il numero di colonna che si desidera restituire per la riga corrispondente della matrice. Per esempio
colIdx = [3;2;1]
Quindi in questo caso in realtà vuoi recuperare gli elementi a (1,3) , (2,2) e (3,1) . Quindi usando l'indicizzazione lineare:
>> colIdx = [3;2;1]; >> rowIdx = 1:length(colIdx); >> idx = sub2ind(size(M), rowIdx, colIdx); >> M(idx) ans = 6 5 4
Restituzione di un elemento più volte
Con indice e indicizzazione lineare puoi anche restituire un elemento più volte ripetendo il suo indice in modo tale
>> M([1,1,1,2,2,2]) ans = 8 8 8 3 3 3
Puoi usarlo per duplicare intere righe e colonne, per esempio per ripetere la prima riga e l'ultima colonna
>> M([1, 1:end], [1:end, end]) ans =
https://riptutorial.com/it/home 11
8 1 6 6 8 1 6 6 3 5 7 7 4 9 2 2
Per ulteriori informazioni, vedere qui .
Aiutare te stesso
MATLAB è dotato di molti script e funzioni incorporati che vanno dalla semplice moltiplicazione a toolbox per il riconoscimento di immagini. Per ottenere informazioni su una funzione che si desidera utilizzare digitare: help functionname nella riga di comando. Consente di prendere l' help funzione di come esempio.
Informazioni su come usarlo possono essere ottenute digitando:
>> help help
nella finestra di comando. Ciò restituirà informazioni sull'uso della funzione di help . Se le informazioni che stai cercando non sono ancora chiare, puoi provare la pagina di documentazione della funzione. Basta digitare:
>> doc help
nella finestra di comando. Questo aprirà la documentazione sfogliabile nella pagina per l' help funzioni fornendo tutte le informazioni necessarie per capire come funziona l''aiuto'.
Questa procedura funziona per tutte le funzioni e i simboli incorporati.
Quando sviluppi le tue funzioni puoi lasciare che abbiano la loro sezione di aiuto aggiungendo commenti nella parte superiore del file di funzione o subito dopo la dichiarazione della funzione.
Esempio per una funzione semplice multiplyby2 salvata nel file multiplyby2.m
function [prod]=multiplyby2(num) % function MULTIPLYBY2 accepts a numeric matrix NUM and returns output PROD % such that all numbers are multiplied by 2 prod=num*2; end
o
% function MULTIPLYBY2 accepts a numeric matrix NUM and returns output PROD % such that all numbers are multiplied by 2 function [prod]=multiplyby2(num) prod=num*2; end
Questo è molto utile quando raccogli il codice settimane / mesi / anni dopo averlo scritto.
https://riptutorial.com/it/home 12
La funzione help e doc fornisce molte informazioni, imparando come utilizzare queste funzionalità per progredire rapidamente e utilizzare MATLAB in modo efficiente.
Lettura di input e scrittura
Proprio come tutti i linguaggi di programmazione, Matlab è progettato per leggere e scrivere in un'ampia varietà di formati. La libreria nativa supporta un gran numero di formati di testo, immagini, video, audio, dati con più formati inclusi in ogni aggiornamento di versione - controlla qui per vedere l'elenco completo dei formati di file supportati e quale funzione utilizzare per importarli.
Prima di tentare di caricare il file, è necessario chiedersi cosa si desidera che i dati diventino e in che modo si aspetta che il computer organizzi i dati per conto dell'utente. Supponi di avere un file txt / csv nel seguente formato:
Fruit,TotalUnits,UnitsLeftAfterSale,SellingPricePerUnit Apples,200,67,$0.14 Bananas,300,172,$0.11 Pineapple,50,12,$1.74
Possiamo vedere che la prima colonna è nel formato di stringhe, mentre la seconda, la terza è numerica, l'ultima colonna è in forma di valuta. Diciamo che vogliamo scoprire quante entrate abbiamo fatto oggi usando Matlab e prima vogliamo caricare in questo file txt / csv. Dopo aver controllato il collegamento, possiamo vedere che il tipo String e Numeric di file txt sono gestiti da textscan . Quindi potremmo provare:
fileID = fopen('dir/test.txt'); %Load file from dir C = textscan(fileID,'%s %f %f %s','Delimiter',',','HeaderLines',1); %Parse in the txt/csv
dove %s suggerisce che l'elemento sia di tipo String, %f suggerisce che l'elemento sia di tipo Float e che il file sia Delimitato da ",". L'opzione HeaderLines chiede a Matlab di saltare le prime righe N mentre l'1 immediatamente dopo significa saltare la prima riga (la linea dell'intestazione).
Ora C è il dato che abbiamo caricato che ha la forma di una matrice di celle di 4 celle, ciascuna contenente la colonna di dati nel file txt / csv.
Quindi per prima cosa vogliamo calcolare quanti frutti abbiamo venduto oggi sottraendo la terza colonna dalla seconda colonna, questo può essere fatto da:
sold = C{2} - C{3}; %C{2} gives the elements inside the second cell (or the second column)
Ora vogliamo moltiplicare questo vettore per il Prezzo per unità, quindi prima dobbiamo convertire quella colonna di stringhe in una colonna di numeri, quindi convertirla in una matrice numerica usando la cell2mat di Matlab la prima cosa che dobbiamo fare è strisciare- fuori dal segno "$", ci sono molti modi per farlo. Il modo più diretto è usare una semplice regex:
D = cellfun(@(x)(str2num(regexprep(x, '\$',''))), C{4}, 'UniformOutput', false);%cellfun allows us to avoid looping through each element in the cell.
https://riptutorial.com/it/home 13
Oppure puoi usare un loop:
for t=1:size(C{4},1) D{t} = str2num(regexprep(C{4}{t}, '\$','')); end E = cell2mat(D)% converts the cell array into a Matrix
La funzione str2num trasforma la stringa che ha i segni "$" spogliati in tipi numerici e cell2mat trasforma la cella di elementi numerici in una matrice di numeri
Ora possiamo moltiplicare le unità vendute per il costo per unità:
revenue = sold .* E; %element-wise product is denoted by .* in Matlab totalrevenue = sum(revenue);
Matrici cellulari
Elementi della stessa classe possono spesso essere concatenati in array (con alcune rare eccezioni, ad esempio i manici di funzione). Gli scalari numerici, per impostazione predefinita del double della classe, possono essere memorizzati in una matrice.
>> A = [1, -2, 3.14, 4/5, 5^6; pi, inf, 7/0, nan, log(0)] A = 1.0e+04 * 0.0001 -0.0002 0.0003 0.0001 1.5625 0.0003 Inf Inf NaN -Inf
I caratteri, che sono di classe char in MATLAB, possono anche essere archiviati in array usando una sintassi simile. Tale array è simile a una stringa in molti altri linguaggi di programmazione.
>> s = ['MATLAB ','is ','fun'] s = MATLAB is fun
Si noti che nonostante entrambi utilizzino le parentesi [ e ] , le classi di risultati sono diverse. Pertanto le operazioni che possono essere eseguite su di loro sono anche diverse.
>> whos Name Size Bytes Class Attributes A 2x5 80 double s 1x13 26 char
In effetti, l'array s non è un array di 'MATLAB ' , 'is ' e 'fun' delle stringhe, è solo una stringa - una matrice di 13 caratteri. Otterresti gli stessi risultati se fosse definito da uno dei seguenti:
>> s = ['MAT','LAB ','is f','u','n']; >> s = ['M','A','T','L','A','B,' ','i','s',' ','f','u','n'];
https://riptutorial.com/it/home 14
Un vettore MATLAB regolare non consente di memorizzare un mix di variabili di classi diverse o alcune stringhe diverse. Questo è dove l'array di cell è utile. Questa è una matrice di celle che ciascuna può contenere alcuni oggetti MATLAB, la cui classe può essere diversa in ogni cella, se necessario. Usa le parentesi graffe { e } intorno agli elementi per archiviarli in un array di celle.
>> C = {A; s} C = [2x5 double] 'MATLAB is fun' >> whos C Name Size Bytes Class Attributes C 2x1 330 cell
Gli oggetti MATLAB standard di qualsiasi classe possono essere memorizzati insieme in un array di celle. Nota che gli array di celle richiedono più memoria per archiviare il loro contenuto.
L'accesso ai contenuti di una cella viene eseguito utilizzando parentesi graffe { e } .
>> C{1} ans = 1.0e+04 * 0.0001 -0.0002 0.0003 0.0001 1.5625 0.0003 Inf Inf NaN -Inf
Si noti che C(1) è diverso da C{1} . Mentre il secondo restituisce il contenuto della cella (e ha un esempio di classe double in out), il primo restituisce un array di celle che è un sottoarray di C Allo stesso modo, se D fosse un array di 10 per 5 celle, D(4:8,1:3) restituirebbe un sub-array di D cui dimensione è 5 per 3 e la cui classe è cell . E la sintassi C{1:2} non ha un singolo oggetto restituito, ma rater restituisce 2 oggetti diversi (simile a una funzione MATLAB con più valori di ritorno):
>> [x,y] = C{1:2} x = 1 -2 3.14 0.8 15625 3.14159265358979 Inf Inf NaN -Inf y = MATLAB is fun
Script e funzioni
Il codice MATLAB può essere salvato in m-files da riutilizzare. m-files hanno l'estensione .m che viene automaticamente associata a MATLAB. Un m-file può contenere uno script o funzioni.
Script
Gli script sono semplicemente file di programma che eseguono una serie di comandi MATLAB in un ordine predefinito.
Gli script non accettano input, né gli script restituiscono l'output. Funzionalmente, gli script sono
https://riptutorial.com/it/home 15
equivalenti a digitare comandi direttamente nella finestra di comando di MATLAB ed essere in grado di riprodurli.
Un esempio di script:
length = 10; width = 3; area = length * width;
Questo script definirà la length , la width e l' area nello spazio di lavoro corrente con i valori 10 , 3 e 30 rispettivamente.
Come detto prima, lo script di cui sopra è funzionalmente equivalente a digitare gli stessi comandi direttamente nella finestra di comando.
>> length = 10; >> width = 3; >> area = length * width;
funzioni
Le funzioni, se confrontate con gli script, sono molto più flessibili ed estensibili. A differenza degli script, le funzioni possono accettare input e restituire l'output al chiamante. Una funzione ha il proprio spazio di lavoro, ciò significa che le operazioni interne delle funzioni non modificheranno le variabili dal chiamante.
Tutte le funzioni sono definite con lo stesso formato di intestazione:
function [output] = myFunctionName(input)
La parola chiave function inizia ogni intestazione di funzione. Segue la lista delle uscite. L'elenco di output può anche essere un elenco separato da virgole di variabili da restituire.
function [a, b, c] = myFunctionName(input)
Il prossimo è il nome della funzione che verrà utilizzata per la chiamata. Questo è generalmente lo stesso nome del nome del file. Ad esempio, salveremmo questa funzione come myFunctionName.m .
Seguendo il nome della funzione è presente l'elenco degli input. Come le uscite, anche questa può essere una lista separata da virgole.
function [a, b, c] = myFunctionName(x, y, z)
Possiamo riscrivere lo script di esempio di prima come una funzione riutilizzabile come la seguente:
function [area] = calcRecArea(length, width) area = length * width; end
https://riptutorial.com/it/home 16
Possiamo chiamare funzioni da altre funzioni o anche da file di script. Ecco un esempio della nostra funzione precedente utilizzata in un file di script.
l = 100; w = 20; a = calcRecArea(l, w);
Come prima, creiamo l , w e a nello spazio di lavoro con i valori rispettivamente di 100 , 20 e 2000 .
Tipi di dati
Ci sono 16 tipi di dati fondamentali , o classi, in MATLAB. Ognuna di queste classi è sotto forma di matrice o matrice. Ad eccezione degli handle di funzione, questa matrice o array ha un minimo di 0 per 0 e può crescere fino a un array n-dimensionale di qualsiasi dimensione. Un handle di funzione è sempre scalare (1 per 1).
Momento importante in MATLAB è che non è necessario utilizzare dichiarazioni di tipo o dichiarazioni di dimensioni per impostazione predefinita. Quando si definisce una nuova variabile, MATLAB lo crea automaticamente e alloca lo spazio di memoria appropriato.
Esempio:
a = 123; b = [1 2 3]; c = '123'; >> whos Name Size Bytes Class Attributes a 1x1 8 double b 1x3 24 double c 1x3 6 char
Se la variabile esiste già, MATLAB sostituisce i dati originali con uno nuovo e alloca il nuovo spazio di archiviazione, se necessario.
Tipi di dati fondamentali
I tipi di dati fondamentali sono: numerico, logical , char , cell , struct , table e function_handle .
Tipi di dati numerici :
Numeri a virgola mobile ( predefinito )
MATLAB rappresenta numeri in virgola mobile in formato a precisione doppia o precisione singola. L'impostazione predefinita è la precisione doppia, ma puoi eseguire qualsiasi numero con precisione singola con una semplice funzione di conversione:
a = 1.23; b = single(a);
•
https://riptutorial.com/it/home 17
>> whos Name Size Bytes Class Attributes a 1x1 8 double b 1x1 4 single
Interi
MATLAB ha quattro classi firmate e quattro classi non firmate. I tipi firmati consentono di lavorare con numeri interi negativi e positivi, ma non possono rappresentare un intervallo di numeri come i tipi senza segno poiché un bit viene utilizzato per designare un segno positivo o negativo per il numero. I tipi senza segno ti offrono una gamma più ampia di numeri, ma questi numeri possono essere solo zero o positivi.
MATLAB supporta la memorizzazione a 1, 2, 4 e 8 byte per i dati interi. È possibile risparmiare memoria e tempo di esecuzione per i programmi se si utilizza il tipo di numero più piccolo che ospita i dati. Ad esempio, non è necessario un numero intero a 32 bit per memorizzare il valore 100.
a = int32(100); b = int8(100); >> whos Name Size Bytes Class Attributes a 1x1 4 int32 b 1x1 1 int8
Per memorizzare i dati come numero intero, è necessario convertire da doppio a tipo intero desiderato. Se il numero che viene convertito in un numero intero ha una parte frazionaria, MATLAB arrotonda il numero intero più vicino. Se la parte frazionaria è esattamente 0.5 , allora dai due interi ugualmente vicini, MATLAB sceglie quello per il quale il valore assoluto è maggiore in grandezza.
a = int16(456);
•
char
Gli array di caratteri forniscono spazio per i dati di testo in MATLAB. In linea con la terminologia di programmazione tradizionale, una matrice (sequenza) di caratteri è definita come una stringa. Non esiste un tipo di stringa esplicito nelle versioni di vendita di MATLAB.
•
logico: valori logici di 1 o 0, rappresentano rispettivamente true e false. Utilizzare per condizioni relazionali e indicizzazione di array. Perché è solo VERO o FALSO ha una dimensione di 1 byte.
a = logical(1);
•
struttura. Un array di strutture è un tipo di dati che raggruppa le variabili di diversi tipi di dati utilizzando contenitori di dati chiamati campi . Ogni campo può contenere qualsiasi tipo di
•
https://riptutorial.com/it/home 18
dati. Accedere ai dati in una struttura utilizzando la notazione dei punti del nome structName.fieldName.
field1 = 'first'; field2 = 'second'; value1 = [1 2 3 4 5]; value2 = 'sometext'; s = struct(field1,value1,field2,value2);
Per accedere a value1, ciascuna delle seguenti sintassi è equivalente
s.first or s.(field1) or s.('first')
Possiamo accedere esplicitamente a un campo che sappiamo esistere con il primo metodo o passare una stringa o creare una stringa per accedere al campo nel secondo esempio. Il terzo esempio dimostra che la notazione punto genitore prende una stringa, che è la stessa memorizzata nella variabile field1.
le variabili di tabella possono essere di dimensioni e tipi di dati diversi, ma tutte le variabili devono avere lo stesso numero di righe.
Age = [15 25 54]'; Height = [176 190 165]'; Name = {'Mike', 'Pete', 'Steeve'}'; T = table(Name,Age, Height);
•
cellula. È molto utile il tipo di dati MATLAB: l'array di celle è un array in cui ogni elemento può essere di tipo e dimensioni di dati diversi. È uno strumento molto potente per manipolare i dati come desideri.
a = { [1 2 3], 56, 'art'};
o
a = cell(3);
•
la funzione gestisce memorizza un puntatore a una funzione (ad esempio, alla funzione anonima). Ti consente di passare una funzione a un'altra funzione o di chiamare funzioni locali dall'esterno della funzione principale.
•
Ci sono molti strumenti per lavorare con ogni tipo di dati e anche funzioni di conversione dei tipi di dati incorporate ( str2double , table2cell ).
Altri tipi di dati
Esistono diversi tipi di dati aggiuntivi che sono utili in alcuni casi specifici. Loro sono:
Data e ora: matrici per rappresentare le date, l'ora e la durata. datetime('now') restituisce 21-Jul-2016 16:30:16 .
•
https://riptutorial.com/it/home 19
Array categoriali: è il tipo di dati per la memorizzazione di dati con valori da un insieme di categorie discrete. Utile per la memorizzazione di dati non numerici (memoria efficace). Può essere utilizzato in una tabella per selezionare gruppi di righe.
a = categorical({'a' 'b' 'c'});
•
I contenitori di mappe sono una struttura di dati che ha una capacità unica di indicizzazione non solo attraverso i valori numerici scalari ma il vettore di caratteri. Gli indici negli elementi di una mappa sono chiamati chiavi. Queste chiavi, insieme ai valori dei dati associati ad esse, sono memorizzate all'interno della Mappa.
•
Le serie temporali sono vettori di dati campionati nel tempo, in ordine, spesso a intervalli regolari. È utile memorizzare i dati connessi ai timestep e ha molti metodi utili con cui lavorare.
•
Funzioni anonime e maniglie di funzione
Nozioni di base
Le funzioni anonime sono un potente strumento del linguaggio MATLAB. Sono funzioni che esistono localmente, ovvero: nello spazio di lavoro corrente. Tuttavia, non esistono sul percorso MATLAB come una normale funzione, ad esempio in un m-file. Questo è il motivo per cui sono chiamati anonimi, sebbene possano avere un nome come una variabile nello spazio di lavoro.
L'operatore @
Utilizzare l'operatore @ per creare funzioni anonime e handle di funzione. Ad esempio, per creare un handle per la funzione sin (sinusoidale) e usarlo come f :
>> f = @sin f = @sin
Ora f è una maniglia per la funzione sin . Proprio come (nella vita reale) la maniglia di una porta è un modo di usare una porta, una maniglia di funzione è un modo di usare una funzione. Per usare f , gli vengono passati argomenti come se fosse la funzione sin :
>> f(pi/2) ans = 1
f accetta qualsiasi argomento di input accettato dalla funzione sin . Se il sin fosse una funzione che accetta argomenti di input pari a zero (cosa che non fa, ma altri lo fanno, ad esempio la funzione peaks ), f() verrebbe usato per chiamarlo senza argomenti di input.
https://riptutorial.com/it/home 20
Funzioni anonime personalizzate
Funzioni anonime di una variabile
Ovviamente non è utile creare un handle per una funzione esistente, come il sin nell'esempio sopra. È un po 'ridondante in quell'esempio. Tuttavia, è utile creare funzioni anonime che facciano cose personalizzate che altrimenti avrebbero bisogno di essere ripetute più volte o creato una funzione separata per. Come esempio di una funzione anonima personalizzata che accetta una variabile come suo input, somma il seno e il coseno quadrato di un segnale:
>> f = @(x) sin(x)+cos(x).^2 f = @(x)sin(x)+cos(x).^2
Ora f accetta un argomento di input chiamato x . Questo è stato specificato usando parentesi (...) direttamente dopo l'operatore @ . f ora è una funzione anonima di x : f(x) . È usato passando un valore di x in f :
>> f(pi) ans = 1.0000
Un vettore di valori o una variabile può anche essere passato a f , a condizione che vengano utilizzati in modo valido all'interno di f :
>> f(1:3) % pass a vector to f ans = 1.1334 1.0825 1.1212 >> n = 5:7; >> f(n) % pass n to f ans = -0.8785 0.6425 1.2254
Funzioni anonime di più di una variabile
Allo stesso modo è possibile creare funzioni anonime per accettare più di una variabile. Un esempio di una funzione anonima che accetta tre variabili:
>> f = @(x,y,z) x.^2 + y.^2 - z.^2 f = @(x,y,z)x.^2+y.^2-z.^2 >> f(2,3,4) ans = -3
Parametrizzare le funzioni anonime
Le variabili nello spazio di lavoro possono essere utilizzate all'interno della definizione di funzioni anonime. Questo è chiamato parametrizzazione. Ad esempio, per utilizzare una costante c = 2 in
https://riptutorial.com/it/home 21
una funzione anonima:
>> c = 2; >> f = @(x) c*x f = @(x)c*x >> f(3) ans = 6
f(3) usato la variabile c come parametro per moltiplicare con la x fornita. Nota che se il valore di c è impostato su qualcosa di diverso a questo punto, allora viene chiamato f(3) , il risultato non sarebbe diverso. Il valore di c è il valore al momento della creazione della funzione anonima:
>> c = 2; >> f = @(x) c*x; >> f(3) ans = 6 >> c = 3; >> f(3) ans = 6
Gli argomenti di input per una funzione anonima non si riferiscono alle variabili di workspace
Si noti che l'utilizzo del nome di variabili nell'area di lavoro come uno degli argomenti di input di una funzione anonima (ad esempio, utilizzando @(...) ) non utilizzerà i valori di tali variabili. Invece, vengono trattati come variabili diverse nell'ambito della funzione anonima, ovvero: la funzione anonima ha il proprio spazio di lavoro privato in cui le variabili di input non si riferiscono mai alle variabili dallo spazio di lavoro principale. L'area di lavoro principale e l'area di lavoro della funzione anonima non conoscono i rispettivi contenuti. Un esempio per illustrare questo:
>> x = 3 % x in main workspace x = 3 >> f = @(x) x+1; % here x refers to a private x variable >> f(5) ans = 6 >> x x = 3
Il valore di x dallo spazio di lavoro principale non viene utilizzato all'interno di f . Inoltre, nello spazio di lavoro principale x è rimasto intatto. Nell'ambito di f , i nomi delle variabili tra parentesi dopo l'operatore @ sono indipendenti dalle variabili dello spazio di lavoro principale.
Le funzioni anonime sono memorizzate in variabili
https://riptutorial.com/it/home 22
Una funzione anonima (o, più precisamente, la funzione handle che punta a una funzione anonima) è memorizzata come qualsiasi altro valore nello spazio di lavoro corrente: In una variabile (come abbiamo fatto sopra), in un array di celle ( {@(x)x.^2,@(x)x+1} ), o anche in una proprietà (come h.ButtonDownFcn per la grafica interattiva). Ciò significa che la funzione anonima può essere trattata come qualsiasi altro valore. Quando lo si archivia in una variabile, ha un nome nello spazio di lavoro corrente e può essere modificato e cancellato proprio come le variabili che contengono i numeri.
Metti diversamente: un handle di funzione (sia nella forma @sin che per una funzione anonima) è semplicemente un valore che può essere memorizzato in una variabile, proprio come può esserlo una matrice numerica.
Uso avanzato
Passaggio delle funzioni alle altre funzioni
Poiché gli handle di funzione sono trattati come variabili, possono essere passati a funzioni che accettano handle di funzione come argomenti di input.
Un esempio: una funzione viene creata in un m-file che accetta un handle di funzione e un numero scalare. Quindi chiama la funzione handle passandogli 3 e quindi aggiunge il numero scalare al risultato. Il risultato è restituito.
Contenuto di funHandleDemo.m :
function y = funHandleDemo(fun,x) y = fun(3); y = y + x;
Salvalo da qualche parte nel percorso, ad esempio nella cartella corrente di MATLAB. Ora funHandleDemo può essere usato come segue, ad esempio:
>> f = @(x) x^2; % an anonymous function >> y = funHandleDemo(f,10) % pass f and a scalar to funHandleDemo y = 19
L'handle di un'altra funzione esistente può essere passato a funHandleDemo :
>> y = funHandleDemo(@sin,-5) y = -4.8589
Nota come @sin era un modo rapido per accedere alla funzione sin senza prima averlo memorizzato in una variabile usando f = @sin .
Utilizzo di bsxfun , cellfun e funzioni simili con funzioni anonime
https://riptutorial.com/it/home 23
MATLAB ha alcune funzioni integrate che accettano le funzioni anonime come input. Questo è un modo per eseguire molti calcoli con un numero minimo di linee di codice. Ad esempio bsxfun , che esegue operazioni binarie elemento per elemento, vale a dire: applica una funzione su due vettori o matrici in modo elemento per elemento. Normalmente, ciò richiederebbe l'uso di for -loops, che spesso richiede la preallocazione per la velocità. Usando bsxfun questo processo è velocizzato. Nell'esempio seguente viene illustrato questo utilizzo di tic e toc , due funzioni che possono essere utilizzate per calcolare quanto tempo richiede il codice. Calcola la differenza di ogni elemento della matrice dalla media della colonna della matrice.
A = rand(50); % 50-by-50 matrix of random values between 0 and 1 % method 1: slow and lots of lines of code tic meanA = mean(A); % mean of every matrix column: a row vector % pre-allocate result for speed, remove this for even worse performance result = zeros(size(A)); for j = 1:size(A,1) result(j,:) = A(j,:) - meanA; end toc clear result % make sure method 2 creates its own result % method 2: fast and only one line of code tic result = bsxfun(@minus,A,mean(A)); toc
L'esecuzione dell'esempio sopra comporta due output:
Elapsed time is 0.015153 seconds. Elapsed time is 0.007884 seconds.
Queste linee provengono dalle funzioni di toc , che stampano il tempo trascorso dall'ultima chiamata alla funzione tic .
La chiamata bsxfun applica la funzione nel primo argomento di input agli altri due argomenti di input. @minus è un nome lungo per la stessa operazione che farebbe il segno meno. È possibile che sia stata specificata una funzione anonimo o handle ( @ ) diversa per qualsiasi altra funzione, purché accetta A e mean(A) come input per generare un risultato significativo.
Soprattutto per grandi quantità di dati in matrici di grandi dimensioni, bsxfun può velocizzare molto le cose. Rende anche il codice più pulito, anche se potrebbe essere più difficile da interpretare per le persone che non conoscono MATLAB o bsxfun . (Si noti che in MATLAB R2016a e versioni successive, molte operazioni che precedentemente utilizzavano bsxfun non ne hanno più bisogno: la A-mean(A) funziona direttamente e in alcuni casi può anche essere più veloce).
Leggi Iniziare con MATLAB Language online: https://riptutorial.com/it/matlab/topic/235/iniziare-con-matlab-language
https://riptutorial.com/it/home 24
Capitolo 2: Applicazioni finanziarie
Examples
Camminata casuale
Di seguito è riportato un esempio che visualizza 5 percorsi casuali monodimensionali di 200 passaggi:
y = cumsum(rand(200,5) - 0.5); plot(y) legend('1', '2', '3', '4', '5') title('random walks')
Nel codice precedente, y è una matrice di 5 colonne, ciascuna della lunghezza 200. Poiché x è omesso, per impostazione predefinita i numeri di riga di y (equivalente all'utilizzo di x=1:200 come asse x). In questo modo la funzione di plot traccia più vettori di Y contro lo stesso vettore x, ognuno con un colore diverso automaticamente.
Moto mariano geometrico univariato
Le dinamiche del Geometric Brownian Motion (GBM) sono descritte dalla seguente equazione differenziale stocastica (SDE):
https://riptutorial.com/it/home 25
Posso usare la soluzione esatta per l'SDE
per generare percorsi che seguono un GBM.
Dati parametri giornalieri per una simulazione di un anno
mu = 0.08/250; sigma = 0.25/sqrt(250); dt = 1/250; npaths = 100; nsteps = 250; S0 = 23.2;
possiamo ottenere il Brownian Motion (BM) W partire da 0 e usarlo per ottenere il GBM a partire da S0
% BM epsilon = randn(nsteps, npaths); W = [zeros(1,npaths); sqrt(dt)*cumsum(epsilon)]; % GBM t = (0:nsteps)'*dt; Y = bsxfun(@plus, (mu-0.5*sigma.^2)*t, sigma*W); Y = S0*exp(Y);
Che produce i percorsi
plot(Y)
https://riptutorial.com/it/home 26
Leggi Applicazioni finanziarie online: https://riptutorial.com/it/matlab/topic/1197/applicazioni-finanziarie
https://riptutorial.com/it/home 27
Capitolo 3: Best practice di MATLAB
Osservazioni
Questo argomento mostra le migliori pratiche che la comunità ha imparato nel tempo.
Examples
Mantenere le linee brevi
Usa il carattere di continuazione (puntini di sospensione) ... per continuare la frase lunga.
Esempio:
MyFunc( parameter1,parameter2,parameter3,parameter4, parameter5, parameter6,parameter7, parameter8, parameter9)
può essere sostituito da:
MyFunc( parameter1, ... parameter2, ... parameter3, ... parameter4, ... parameter5, ... parameter6, ... parameter7, ... parameter8, ... parameter9)
Codice di rientro correttamente
La corretta indentazione non solo conferisce un aspetto estetico ma aumenta anche la leggibilità del codice.
Ad esempio, considera il seguente codice:
%no need to understand the code, just give it a look n = 2; bf = false; while n>1 for ii = 1:n for jj = 1:n if ii+jj>30 bf = true; break end end if bf break end
https://riptutorial.com/it/home 28
end if bf break end n = n + 1; end
Come puoi vedere, devi dare un'occhiata attenta per vedere quale loop e if dichiarazioni stanno finendo dove. Con indentazione intelligente, otterrai questo aspetto:
n = 2; bf = false; while n>1 for ii = 1:n for jj = 1:n if ii+jj>30 bf = true; break end end if bf break end end if bf break end n = n + 1; end
Questo indica chiaramente l'inizio e la fine dell'istruzione loop / if .
Puoi fare indentazione intelligente tramite: • selezionando tutto il tuo codice ( Ctrl + A )
• quindi premere Ctrl + I o fare clic dalla barra di modifica.
Usa assert
Matlab consente di passare silenziosamente a errori molto banali, il che potrebbe causare un errore molto più avanti durante l'esecuzione, rendendo difficile il debug. Se assumi qualcosa sulle tue variabili, validalo .
function out1 = get_cell_value_at_index(scalar1,cell2) assert(isscalar(scalar1),'1st input must be a scalar')
https://riptutorial.com/it/home 29
assert(iscell(cell2),'2nd input must be a cell array') assert(numel(cell2) >= scalar1),'2nd input must have more elements than the value of the 1st input') assert(~isempty(cell2{scalar1}),'2nd input at location is empty') out1 = cell2{scalar1};
Evitare i loop
Il più delle volte, i loop sono computazionalmente costosi con Matlab. Il tuo codice sarà più veloce di ordini se usi la vettorizzazione. Inoltre, rende spesso il tuo codice più modulare, facilmente modificabile e più facile da eseguire il debug. Lo svantaggio principale è che devi prendere tempo per pianificare le strutture dati e gli errori di dimensione sono più facili da ottenere.
Esempi
Non scrivere
for t=0:0.1:2*pi R(end+1)=cos(t); end
ma
t=0:0.1:2*pi; R=cos(t)
Non scrivere
for i=1:n for j=1:m c(i,j)=a(i)+2*b(j); end end
Ma qualcosa di simile a
c=repmat(a.',1,m)+2*repmat(b,n,1)
Per maggiori dettagli, vedere la vettorizzazione
Crea un nome univoco per il file temporaneo
Durante la codifica di uno script o di una funzione, può essere necessario che uno o più file temporanei siano necessari per, ad esempio, memorizzare alcuni dati.
Per evitare di sovrascrivere un file esistente o per ombreggiare una funzione MATLAB, è possibile utilizzare la funzione tempname per generare un nome univoco per un file temporaneo nella
https://riptutorial.com/it/home 30
cartella temporanea del sistema.
my_temp_file=tempname
Il nome file viene generato senza l'estensione; può essere aggiunto concatenando l'estensione desiderata al nome generato da tempname
my_temp_file_with_ext=[tempname '.txt']
La posizione della cartella temporanea del sistema può essere recuperata mediante il salvataggio della funzione tempdir .
Se, durante l'esecuzione della funzione / script, il file temporaneo non è più necessario, può essere eliminato utilizzando la funzione delete
Dal momento che delete non chiedere conferma, potrebbe essere utile per impostare sulla possibilità di spostare il file da eliminare nella on recycle cartella.
Questo può essere fatto usando la funzione recycle in questo modo:
recycle('on')
Nel seguente esempio, un possibile uso delle funzioni tempname , delete e recycle viene proposto.
% % Create some example data % theta=0:.1:2*pi; x=cos(theta); y=sin(theta); % % Generate the temporary filename % my_temp_file=[tempname '.mat']; % % Split the filename (path, name, extension) and display them in a message box [tmp_file_path,tmp_file_name, tmp_file_ext]=fileparts(my_temp_file) uiwait(msgbox(sprintf('Path= %s\nName= %s\nExt= %s', ... tmp_file_path,tmp_file_name,tmp_file_ext),'TEMPORARY FILE')) % % Save the varaibles in a temporary file % save(my_temp_file,'x','y','theta') % % Load the varaibles from the temporary file % load(my_temp_file) % % Set the reclycle option on % recycle('on') % % Delete the temporary file %
https://riptutorial.com/it/home 31
delete(my_temp_file)
Avvertimento
Il nome file temporaneo viene generato utilizzando il metodo java.util.UUID.randomUUID ( randomUUID ).
Se MATLAB viene eseguito senza JVM, il nome file temporaneo viene generato utilizzando matlab.internal.timing.timing base al contatore e al tempo della CPU. In questo caso il nome file temporaneo non è garantito come univoco.
Utilizzare validateattributes
La funzione validateattributes può essere utilizzata per convalidare un array rispetto a un insieme di specifiche
Può quindi essere utilizzato per convalidare l'input fornito a una funzione.
Nell'esempio seguente, la funzione test_validateattributes richiede tre input
function test_validateattributes(input_1,input_2,input_3)
Le specifiche di input sono:
matrice_1:
classe: doppio○
dimensione: [3,2]○
valori: gli elementi non devono essere NaN○
•
char_array:
classe: char○
valore: la stringa non deve essere vuota○
•
array_3
classe: doppio○
dimensione: [5 1]○
valori: gli elementi devono essere reali○
•
Per validare i tre input, la funzione validateattributes può essere chiamata con la seguente sintassi:
validateattributes(A,classes,attributes,funcName,varName,argIndex)
dove:
A è la matrice da rendere bonificata•classes : è il type dell'array (es. single , double , logical )•
https://riptutorial.com/it/home 32
attributes : sono gli attributi che l'array di input deve corrispondere (es. [3,2], size per specificare la dimensione dell'array, nonnan per specificare che l'array non deve avere valori NaN)
•
funcName : è il nome della funzione in cui si verifica la convalida. Questo argomento viene utilizzato nella generazione del messaggio di errore (se presente)
•
varName : è il nome dell'array in fase di validazione. Questo argomento viene utilizzato nella generazione del messaggio di errore (se presente)
•
argIndex : è la posizione della matrice inpurt nella lista di input. Questo argomento viene utilizzato nella generazione del messaggio di errore (se presente)
•
Nel caso in cui uno o più input non corrispondano alle specifiche, viene generato un messaggio di errore.
In caso di più di un input non valido, la validazione si interrompe quando viene trovata la prima mancata corrispondenza.
Questa è la function test_validateattributes in cui è stata implementata la convalida dell'input.
Poiché la funzione richiede tre ingressi, un primo controllo del numero di ingresso disponibile viene eseguita utilizzando il fnction nargin .
function test_validateattributes(array_1,char_array_1,array_3) % % Check for the number of expected input: if the number of input is less % than the require, the function exits with an error message % if(nargin ~= 3) error('Error: TEST_VALIDATEATTRIBUTES requires 3 input, found %d',nargin) end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Definition of the expected characteristics of the first input % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % INPUT #1 name (only used in the generation of the error message) % input_1_name='array_1'; % % INPUT #1 position (only used in the generation of the error message) % input_1_position=1; % % Expected CLASS of the first input MUST BE "double" % input_1_class={'double'}; % % Expected ATTRIBUTES of the first input % SIZE: MUST BE [3,2] % input_1_size_attribute='size'; input_1_size=[3,2]; % % VALUE CHECK: the element MUST BE NOT NaN % input_1_value_type='nonnan'; %
https://riptutorial.com/it/home 33
% Build the INPUT 1 attributes % input_1_attributes={input_1_size_attribute,input_1_size, ... input_1_value_type}; % % CHECK THE VALIDITY OF THE FIRST INPUT % validateattributes(array_1, ... input_1_class,input_1_attributes,'', ... input_1_name,input_1_position); % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Definition of the expected characteristics of the second input % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % INPUT #1 name (only used in the generation of the error message) % input_2_name='char_array_1'; % % INPUT #2 position (only used in the generation of the error message) % input_2_position=2; % % Expected CLASS of the first input MUST BE "string" % input_2_class={'char'}; % % VALUE CHECK: the element must be not NaN % input_2_size_attribute='nonempty'; % % Build the INPUT 2 attributes % input_2_attributes={input_2_size_attribute}; % % CHECK THE VALIDITY OF THE SECOND INPUT % validateattributes(char_array_1, ... input_2_class,input_2_attributes,'', ... input_2_name,input_2_position); % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Definition of the expected characteristics of the third input % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % INPUT #3 name (only used in the generation of the error message) % input_3_name='array_3'; % % INPUT #3 position (only used in the generation of the error message) % input_3_position=3; % % Expected CLASS of the first input MUST BE "double" % input_3_class={'double'}; % % Expected ATTRIBUTES of the first input % SIZE: must be [5] input_3_size_attribute='size';
https://riptutorial.com/it/home 34
input_3_size=[5 1]; % VALUE CHECK: the elements must be real input_3_value_type='real'; % % Build the INPUT 3 attributes % input_3_attributes={input_3_size_attribute,input_3_size, ... input_3_value_type}; % % CHECK THE VALIDITY OF THE FIRST INPUT % validateattributes(array_3, ... input_3_class,input_3_attributes,'', ... input_3_name,input_3_position); disp('All the three input are OK')
Il seguente script può essere utilizzato per testare l'implementazione della procedura di convalida.
Genera i tre input richiesti e, casualmente, li rende non validi.
% % Generate the first input % n_rows=randi([2 3],1); n_cols=2; input_1=randi([20 30],n_rows,n_cols); % % Generate the second input % if(rand > 0.5) input_2='This is a string'; else input_2=''; end % % Generate the third input % input_3=acos(rand(5,1)*1.2); % % Call the test_validateattributes function with the above generated input % input_1 input_2 input_3 % test_validateattributes(input_1,input_2,input_3)
Questi sono un paio di esempi di input errati rilevati dalla funzione validateattributes :
Input sbagliato
input_1 = 23 22 26 28 input_2 =
https://riptutorial.com/it/home 35
'' input_3 = 0.0000 + 0.4455i 1.2420 + 0.0000i 0.4063 + 0.0000i 1.3424 + 0.0000i 1.2186 + 0.0000i Error using test_validateattributes (line 44) Expected input number 1, array_1, to be of size 3x2 when it is actually size 2x2.
Input sbagliato
input_1 = 22 24 21 25 26 27 input_2 = This is a string input_3 = 1.1371 + 0.0000i 0.6528 + 0.0000i 1.0479 + 0.0000i 0.0000 + 0.1435i 0.0316 + 0.0000i Error using test_validateattributes (line 109) Expected input number 3, array_3, to be real.
Input valido
input_1 = 20 25 25 28 24 23 input_2 = This is a string input_3 = 0.9696 1.5279 1.3581 0.5234 0.9665 All the three input are OK
https://riptutorial.com/it/home 36
Block Comment Operator
È una buona pratica aggiungere commenti che descrivano il codice. È utile per gli altri e anche per il programmatore quando viene restituito in seguito. Una singola riga può essere commentata usando il simbolo % o usando la combinazione di Ctrl+R Per rimuovere il commento da una riga precedentemente commentata, rimuovere il simbolo % o utilizzare Shortkey Crtl+T
Mentre commentare un blocco di codice può essere fatto aggiungendo un simbolo % all'inizio di ogni riga, le versioni più recenti di MATLAB (dopo il 2015a) consentono di utilizzare l' Operatore commento blocchi %{ code %} . Questo operatore aumenta la leggibilità del codice. Può essere utilizzato sia per la creazione di commenti sul codice che per la documentazione della guida alle funzioni. Il blocco può essere piegato e aperto per aumentare la leggibilità del codice.
Come si può vedere, gli operatori %{ e %} devono apparire da soli sulle linee. Non includere nessun altro testo su queste linee.
function y = myFunction(x) %{
https://riptutorial.com/it/home 37
myFunction Binary Singleton Expansion Function y = myFunction(x) applies the element-by-element binary operation specified by the function handle FUNC to arrays A and B, with implicit expansion enabled. %} %% Compute z(x, y) = x.*sin(y) on a grid: % x = 1:10; y = x.'; %{ z = zeros(numel(x),numel(y)); for ii=1:numel(x) for jj=1:numel(y) z(ii,jj) = x(ii)*sin(y(jj)); end end %} z = bsxfun(@(x, y) x.*sin(y), x, y); y = y + z; end
Leggi Best practice di MATLAB online: https://riptutorial.com/it/matlab/topic/2887/best-practice-di-matlab
https://riptutorial.com/it/home 38
Capitolo 4: condizioni
Sintassi
se espressione ... fine•se espressione ... altro ... fine•se espressione ... elseif espressione ... fine•se espressione ... elseif espressione ... altro ... fine•
Parametri
Parametro Descrizione
espressione un'espressione che ha un significato logico
Examples
Condizione IF
Le condizioni sono una parte fondamentale di quasi ogni parte del codice. Sono utilizzati per eseguire alcune parti del codice solo in alcune situazioni, ma non in altre. Diamo un'occhiata alla sintassi di base:
a = 5; if a > 10 % this condition is not fulfilled, so nothing will happen disp('OK') end if a < 10 % this condition is fulfilled, so the statements between the if...end are executed disp('Not OK') end
Produzione:
Not OK
In questo esempio vediamo che if costituito da 2 parti: la condizione e il codice da eseguire se la condizione è vera. Il codice è tutto scritto dopo la condizione e prima della end di quello if . La prima condizione non è stata soddisfatta e quindi il codice al suo interno non è stato eseguito.
Ecco un altro esempio:
a = 5; if a ~= a+1 % "~=" means "not equal to" disp('It''s true!') % we use two apostrophes to tell MATLAB that the ' is part of the
https://riptutorial.com/it/home 39
string end
La condizione sopra sarà sempre vera e mostrerà l'output It's true! .
Possiamo anche scrivere:
a = 5; if a == a+1 % "==" means "is equal to", it is NOT the assignment ("=") operator disp('Equal') end
Questa volta la condizione è sempre falsa, quindi non otterremo mai l'output Equal .
Non c'è molto da usare per condizioni che sono sempre vere o false, però, perché se sono sempre false possiamo semplicemente cancellare questa parte del codice, e se sono sempre vere, allora la condizione non è necessaria.
Condizione IF-ELSE
In alcuni casi si vuole eseguire un codice alternativo se la condizione è falsa, per questo usiamo opzionale else parte:
a = 20; if a < 10 disp('a smaller than 10') else disp('a bigger than 10') end
Qui vediamo che poiché a non è inferiore a 10 la seconda parte del codice, dopo che il else è stato eseguito e otteniamo a bigger than 10 output a bigger than 10 . Ora guardiamo un altro tentativo:
a = 10; if a > 10 disp('a bigger than 10') else disp('a smaller than 10') end
In questo esempio mostra che non abbiamo verificato se a è effettivamente inferiore a 10 e riceviamo un messaggio sbagliato perché la condizione controlla solo l'espressione così com'è, e QUALSIASI caso che non sia uguale a true ( a = 10 ) causerà il seconda parte da eseguire.
Questo tipo di errore è una trappola molto comune sia per i principianti che per i programmatori esperti, specialmente quando le condizioni diventano complesse e devono essere sempre tenute a mente
Condizione IF-ELSEIF
Usando il else possiamo eseguire qualche compito quando la condizione non è soddisfatta. Ma
https://riptutorial.com/it/home 40
cosa succede se vogliamo verificare una seconda condizione nel caso in cui il primo fosse falso. Possiamo farlo in questo modo:
a = 9; if mod(a,2)==0 % MOD - modulo operation, return the remainder after division of 'a' by 2 disp('a is even') else if mod(a,3)==0 disp('3 is a divisor of a') end end OUTPUT: 3 is a divisor of a
Questo è anche chiamato "condizione nidificata" , ma qui abbiamo un caso specifico che può migliorare la leggibilità del codice e ridurre la possibilità di errore anr - possiamo scrivere:
a = 9; if mod(a,2)==0 disp('a is even') elseif mod(a,3)==0 disp('3 is a divisor of a') end OUTPUT: 3 is a divisor of a
usando il elseif siamo in grado di controllare un'altra espressione all'interno dello stesso blocco di condizioni, e questo non è limitato a un tentativo:
a = 25; if mod(a,2)==0 disp('a is even') elseif mod(a,3)==0 disp('3 is a divisor of a') elseif mod(a,5)==0 disp('5 is a divisor of a') end OUTPUT: 5 is a divisor of a
Prestare particolare attenzione quando si sceglie di utilizzare elseif in una riga, dal momento che solo uno di essi verrà eseguito da tutti i if alla end blocco. Quindi, nel nostro esempio, se vogliamo mostrare tutti i divisori di a (da quelli che controlliamo esplicitamente) l'esempio sopra non andrà bene:
a = 15; if mod(a,2)==0 disp('a is even') elseif mod(a,3)==0 disp('3 is a divisor of a') elseif mod(a,5)==0 disp('5 is a divisor of a')
https://riptutorial.com/it/home 41
end OUTPUT: 3 is a divisor of a
non solo 3, ma anche 5 è un divisore di 15, ma la parte che controlla la divisione per 5 non viene raggiunta se nessuna delle espressioni sopra di esso era vera.
Infine, possiamo aggiungere un else (e solo uno ) dopo tutte le condizioni elseif per eseguire un codice quando nessuna delle condizioni di cui sopra sono soddisfatte:
a = 11; if mod(a,2)==0 disp('a is even') elseif mod(a,3)==0 disp('3 is a divisor of a') elseif mod(a,5)==0 disp('5 is a divisor of a') else disp('2, 3 and 5 are not divisors of a') end OUTPUT: 2, 3 and 5 are not divisors of a
Condizioni nidificate
Quando usiamo una condizione in un'altra condizione, diciamo che le condizioni sono "annidate". Un caso speciale di condizioni nidificate è dato dall'opzione elseif , ma ci sono molti altri modi per usare i conditoni nidificati. Esaminiamo il seguente codice:
a = 2; if mod(a,2)==0 % MOD - modulo operation, return the remainder after division of 'a' by 2 disp('a is even') if mod(a,3)==0 disp('3 is a divisor of a') if mod(a,5)==0 disp('5 is a divisor of a') end end else disp('a is odd') end
Per a=2 , l'output sarà a is even , che è corretto. Per a=3 , l'output sarà a is odd , che è anche corretto, ma manca il controllo se 3 è un divisore di a . Questo perché le condizioni sono nidificate, quindi solo se la prima è true , allora passiamo a quella interna, e se a è dispari, nessuna delle condizioni interne è nemmeno controllata. Questo è alquanto opposto all'uso di elseif dove solo se la prima condizione è false quella che controlliamo la prossima. Che ne dici di controllare la divisione per 5? solo un numero che ha 6 come divisore (entrambi 2 e 3) verrà controllato per la divisione per 5, e possiamo testare e vedere che per a=30 l'output è:
a is even
https://riptutorial.com/it/home 42
3 is a divisor of a 5 is a divisor of a
Dovremmo anche notare due cose:
La posizione della end nel posto giusto per ciascun if è cruciale perché l'insieme di condizioni funzioni come previsto, quindi l'indentazione è più che una buona raccomandazione qui.
1.
La posizione del else affermazione è anche fondamentale, perché abbiamo bisogno di sapere in quale if (e ci potrebbero essere molti di loro) vogliamo fare qualcosa nel caso in cui l'espressione, se false .
2.
Diamo un'occhiata ad un altro esempio:
for a = 5:10 % the FOR loop execute all the code within it for every a from 5 to 10 ch = num2str(a); % NUM2STR converts the integer a to a character if mod(a,2)==0 if mod(a,3)==0 disp(['3 is a divisor of ' ch]) elseif mod(a,4)==0 disp(['4 is a divisor of ' ch]) else disp([ch ' is even']) end elseif mod(a,3)==0 disp(['3 is a divisor of ' ch]) else disp([ch ' is odd']) end end
E l'output sarà:
5 is odd 3 is a divisor of 6 7 is odd 4 is a divisor of 8 3 is a divisor of 9 10 is even
vediamo che abbiamo solo 6 righe per 6 numeri, perché le condizioni sono nidificate in un modo che garantisce solo una stampa per numero, e anche (sebbene non possano essere viste direttamente dall'output) non sono preformati controlli extra, quindi se un numero non è nemmeno lì non ha senso controllare se 4 è uno dei suoi divisori.
Leggi condizioni online: https://riptutorial.com/it/matlab/topic/3806/condizioni
https://riptutorial.com/it/home 43
Capitolo 5: Controllo della colorazione di sottotrama in Matlab
introduzione
Mentre stavo lottando con questo più di una volta, e il web non è chiaro su cosa fare, ho deciso di prendere ciò che è là fuori, aggiungendone alcuni dei miei per spiegare come creare sottotrame con una colorbar e loro sono ridimensionati in base ad esso.
Ho provato questo usando l'ultimo Matlab ma sono abbastanza sicuro che funzionerà nelle versioni precedenti.
Osservazioni
L'unica cosa che devi risolvere da solo è il posizionamento della barra dei colori (se vuoi visualizzarla del tutto). questo dipenderà dal numero di grafici che hai e dall'orientamento della barra.
La posizione e la dimensione sono definite usando 4 parametri - x_start, y_start, x_width, y_width. Di solito il grafico viene ridimensionato in unità normalizzate in modo che l'angolo in basso a sinistra corrisponda a (0,0) e in alto a destra a (1,1).
Examples
Come è fatto
Questo è un codice semplice che crea 6 sottototoli 3d e alla fine sincronizza il colore visualizzato in ognuno di essi.
c_fin = [0,0]; [X,Y] = meshgrid(1:0.1:10,1:0.1:10); figure; hold on; for i = 1 : 6 Z(:,:,i) = i * (sin(X) + cos(Y)); ax(i) = subplot(3,2,i); hold on; grid on; surf(X, Y, Z(:,:,i)); view(-26,30); colormap('jet'); ca = caxis; c_fin = [min(c_fin(1),ca(1)), max(c_fin(2),ca(2))]; end %%you can stop here to see how it looks before we color-manipulate c = colorbar('eastoutside'); c.Label.String = 'Units';
https://riptutorial.com/it/home 44
set(c, 'Position', [0.9, 0.11, 0.03, 0.815]); %%you may want to play with these values pause(2); %%need this to allow the last image to resize itself before changing its axes for i = 1 : 6 pos=get(ax(i), 'Position'); axes(ax(i)); set(ax(i), 'Position', [pos(1) pos(2) 0.85*pos(3) pos(4)]); set(ax(i),'Clim', c_fin); %%this is where the magic happens end
Leggi Controllo della colorazione di sottotrama in Matlab online: https://riptutorial.com/it/matlab/topic/10913/controllo-della-colorazione-di-sottotrama-in-matlab
https://riptutorial.com/it/home 45
Capitolo 6: Debug
Sintassi
dbstop nel file nella posizione se espressione•
Parametri
Parametro Dettagli
fileNome del .m file (senza estensione), ad esempio fit . Questo parametro è (obbligatorio) a meno che non si imposti tipi speciali di breakpoint condizionale come dbstop if error o dbstop if naninf .
PosizioneNumero di riga in cui deve essere inserito il punto di interruzione. Se la riga specificata non contiene codice eseguibile, il punto di interruzione verrà posizionato sulla prima riga valida dopo quella specificata.
espressioneQualsiasi espressione o combinazione di questi che valuti un valore booleano. Esempi: ind == 1 , nargin < 4 && isdir('Q:\') .
Examples
Lavorare con i punti di interruzione
Definizione
Nello sviluppo del software, un punto di interruzione è un punto di arresto o di pausa intenzionale in un programma, creato per scopi di debug.
Più in generale, un punto di interruzione è un mezzo per acquisire conoscenze su un programma durante la sua esecuzione. Durante l'interruzione, il programmatore ispeziona l'ambiente di test (registri di uso generale, memoria, registri, file, ecc.) Per scoprire se il programma funziona come previsto. In pratica, un breakpoint consiste in una o più condizioni che determinano quando l'esecuzione di un programma deve essere interrotta.
-Wikipedia
Punti di interruzione in MATLAB
https://riptutorial.com/it/home 46
Motivazione
In MATLAB, quando l'esecuzione si ferma su un punto di interruzione, le variabili esistenti nello spazio di lavoro corrente (noto anche come scope ) o in qualsiasi area di lavoro chiamante possono essere ispezionate (e di solito anche modificate).
Tipi di punti di interruzione
MATLAB consente agli utenti di inserire due tipi di punti di interruzione nei file .m :
Punti di interruzione standard (o " non limitati ") (mostrati in rosso) - sospendono l'esecuzione ogni volta che viene raggiunta la linea evidenziata.
•
Punti di rottura "condizionali" (indicati in giallo) - sospendono l'esecuzione ogni volta che viene raggiunta la linea contrassegnata E la condizione definita nel punto di interruzione viene valutata come true .
•
Posizionamento dei punti di interruzione
Entrambi i tipi di punti di interruzione possono essere creati in diversi modi:
Utilizzando la GUI di MATLAB Editor, facendo clic con il pulsante destro sulla linea orizzontale accanto al numero di riga.
•
Utilizzando il comando dbstop :
% Create an unrestricted breakpoint: dbstop in file at location % Create a conditional breakpoint: dbstop in file at location if expression % Examples and special cases: dbstop in fit at 99 % Standard unrestricted breakpoint. dbstop in fit at 99 if nargin==3 % Standard conditional breakpoint. dbstop if error % This special type of breakpoint is not limited to a specific file, and % will trigger *whenever* an error is encountered in "debuggable" code. dbstop in file % This will create an unrestricted breakpoint on the first executable line % of "file".
•
https://riptutorial.com/it/home 47
dbstop if naninf % This special breakpoint will trigger whenever a computation result % contains either a NaN (indicates a division by 0) or an Inf
Utilizzo delle scorciatoie da tastiera: la chiave predefinita per la creazione di un punto di interruzione standard su Windows è F12 ; la chiave predefinita per i punti di interruzione condizionali non è impostata .
•
Disabilitare e riattivare i punti di interruzione
Disabilitare un punto di interruzione per ignorarlo temporaneamente: i punti di interruzione disabilitati non interrompono l'esecuzione. La disattivazione di un punto di interruzione può essere eseguita in diversi modi:
Fare clic con il pulsante destro del mouse sul cerchio del punto di interruzione rosso / giallo> Disattiva punto di interruzione.
•
Fare clic con il tasto sinistro su un punto di interruzione condizionale (giallo).•Nella scheda Editor> Punti di interruzione> Abilita \ Disabilita.•
Rimozione dei punti di interruzione
Tutti i punti di interruzione rimangono in un file fino a quando non vengono rimossi, manualmente o automaticamente. I punti di interruzione vengono cancellati automaticamente quando si termina la sessione MATLAB (cioè terminando il programma). La cancellazione manuale dei punti di interruzione avviene in uno dei seguenti modi:
Utilizzando il comando dbclear :
dbclear all dbclear in file dbclear in file at location dbclear if condition
•
Fare clic con il pulsante sinistro su un'icona di punto di interruzione standard o un'icona di punto di interruzione condizionale disabilitata.
•
Fare clic con il tasto destro su qualsiasi punto di interruzione> Cancella punto di interruzione.
•
Nella scheda Editor> Punti di interruzione> Cancella tutto.•
Nelle versioni pre-R2015b di MATLAB, utilizzando il comando clear .•
Ripresa dell'esecuzione
Quando l'esecuzione viene messa in pausa in un punto di interruzione, esistono due modi per continuare l'esecuzione del programma:
https://riptutorial.com/it/home 48
Esegui la riga corrente e metti nuovamente in pausa prima della riga successiva.
F10 1 nell'Editor, dbstep nella finestra di comando, "Passo" in Barra multifunzione> Editor> DEBUG.
•
Esegui fino al prossimo punto di interruzione (se non ci sono più punti di interruzione, l'esecuzione procede fino alla fine del programma).
F12 1 nell'editor, dbcont nella finestra di comando, "Continua" in Barra multifunzione> Editor> DEBUG.
•
1 - predefinito su Windows.
Debug di codice Java richiamato da MATLAB
Panoramica
Per eseguire il debug delle classi Java richiamate durante l'esecuzione di MATLAB, è necessario eseguire due passaggi:
Esegui MATLAB in modalità di debug JVM.1. Allegare un debugger Java al processo MATLAB.2.
Quando MATLAB viene avviato in modalità di debug JVM, viene visualizzato il seguente messaggio nella finestra di comando:
JVM is being started with debugging enabled. Use "jdb -connect com.sun.jdi.SocketAttach:port=4444" to attach debugger.
Fine MATLAB
Finestre:
Creare un collegamento all'eseguibile MATLAB ( matlab.exe ) e aggiungere il flag -jdb alla fine come mostrato di seguito:
https://riptutorial.com/it/home 49
Quando si esegue MATLAB utilizzando questo collegamento, verrà abilitato il debug JVM.
In alternativa, il file java.opts può essere creato / aggiornato. Questo file è memorizzato in "matlab-root \ bin \ arch", dove "matlab-root" è il directoy di installazione MATLAB e "arch" è l'architettura (ad esempio "win32").
Il seguente dovrebbe essere aggiunto nel file:
-Xdebug -Xrunjdwp:transport=dt_socket,address=1044,server=y,suspend=n
Fine del debugger
IntelliJ IDEA
L'associazione di questo debugger richiede la creazione di una configurazione di "debug remoto" con la porta esposta da MATLAB:
https://riptutorial.com/it/home 50
Quindi viene avviato il debugger:
Se tutto funziona come previsto, verrà visualizzato il seguente messaggio nella console:
https://riptutorial.com/it/home 51
Leggi Debug online: https://riptutorial.com/it/matlab/topic/1045/debug
https://riptutorial.com/it/home 52
Capitolo 7: Disegno
Examples
Circles
L'opzione più semplice per disegnare un cerchio è, ovviamente, la funzione del rectangle .
%// radius r = 2; %// center c = [3 3]; pos = [c-r 2*r 2*r]; rectangle('Position',pos,'Curvature',[1 1]) axis equal
ma la curvatura del rettangolo deve essere impostata su 1 !
Il vettore position definisce il rettangolo, i primi due valori x e y sono nell'angolo in basso a sinistra del rettangolo. Gli ultimi due valori definiscono la larghezza e l'altezza del rettangolo.
pos = [ [x y] width height ]
L' angolo in basso a sinistra del cerchio - sì, questo cerchio ha angoli, quelli immaginari però - è il centro c = [3 3] meno il raggio r = 2 che è [xy] = [1 1] . Larghezza e altezza sono uguali al diametro del cerchio, quindi width = 2*r; height = width;
https://riptutorial.com/it/home 53
Nel caso in cui la scorrevolezza della soluzione di cui sopra non sia sufficiente, non c'è modo di aggirare usando il modo ovvio di disegnare un cerchio reale mediante l'uso di funzioni trigonometriche .
%// number of points n = 1000; %// running variable t = linspace(0,2*pi,n); x = c(1) + r*sin(t); y = c(2) + r*cos(t); %// draw line line(x,y) %// or draw polygon if you want to fill it with color %// fill(x,y,[1,1,1]) axis equal
https://riptutorial.com/it/home 54
frecce
In primo luogo, si può usare la quiver , in cui non si ha a che fare con unità di figure normalizzate non coerenti mediante l'uso di annotation
drawArrow = @(x,y) quiver( x(1),y(1),x(2)-x(1),y(2)-y(1),0 ) x1 = [10 30]; y1 = [10 30]; drawArrow(x1,y1); hold on x2 = [25 15]; y2 = [15 25]; drawArrow(x2,y2)
https://riptutorial.com/it/home 55
Importante è il quinto argomento di quiver : 0 che disabilita un ridimensionamento altrimenti predefinito, in quanto questa funzione viene solitamente utilizzata per tracciare campi vettoriali. (o utilizzare la coppia di valori di proprietà 'AutoScale','off' )
Si può anche aggiungere funzionalità aggiuntive:
drawArrow = @(x,y,varargin) quiver( x(1),y(1),x(2)-x(1),y(2)-y(1),0, varargin{:} ) drawArrow(x1,y1); hold on drawArrow(x2,y2,'linewidth',3,'color','r')
https://riptutorial.com/it/home 56
Se si desiderano punte di freccia diverse, è necessario utilizzare le annotazioni (questa risposta può essere utile Come si modifica lo stile della freccia nella trama del quiver? ).
La dimensione della freccia può essere regolata con la proprietà 'MaxHeadSize' . Purtroppo non è coerente. I limiti degli assi devono essere impostati in seguito.
x1 = [10 30]; y1 = [10 30]; drawArrow(x1,y1,{'MaxHeadSize',0.8,'Color','b','LineWidth',3}); hold on x2 = [25 15]; y2 = [15 25]; drawArrow(x2,y2,{'MaxHeadSize',10,'Color','r','LineWidth',3}); hold on xlim([1, 100]) ylim([1, 100])
C'è un altro tweak per le teste di freccia regolabili:
function [ h ] = drawArrow( x,y,xlimits,ylimits,props ) xlim(xlimits) ylim(ylimits) h = annotation('arrow'); set(h,'parent', gca, ... 'position', [x(1),y(1),x(2)-x(1),y(2)-y(1)], ... 'HeadLength', 10, 'HeadWidth', 10, 'HeadStyle', 'cback1', ... props{:} ); end
https://riptutorial.com/it/home 57
che puoi chiamare dal tuo script come segue:
drawArrow(x1,y1,[1, 100],[1, 100],{'Color','b','LineWidth',3}); hold on drawArrow(x2,y2,[1, 100],[1, 100],{'Color','r','LineWidth',3}); hold on
Ellisse
Per tracciare un'ellisse puoi usare la sua equazione . Un'ellisse ha un asse maggiore e uno minore. Inoltre, vogliamo essere in grado di tracciare l'ellisse su diversi punti centrali. Pertanto scriviamo una funzione i cui input e output sono:
Inputs: r1,r2: major and minor axis respectively C: center of the ellipse (cx,cy) Output: [x,y]: points on the circumference of the ellipse
È possibile utilizzare la seguente funzione per ottenere i punti su un'ellisse e quindi tracciare quei punti.
function [x,y] = getEllipse(r1,r2,C) beta = linspace(0,2*pi,100); x = r1*cos(beta) - r2*sin(beta); y = r1*cos(beta) + r2*sin(beta); x = x + C(1,1); y = y + C(1,2); end
Exmaple:
https://riptutorial.com/it/home 58
[x,y] = getEllipse(1,0.3,[2 3]); plot(x,y);
Poligono (s)
Crea i vettori per mantenere le posizioni x e y dei vertici, inseriscili in patch .
Singolo poligono
X=rand(1,4); Y=rand(1,4); h=patch(X,Y,'red');
https://riptutorial.com/it/home 59
Poligoni multipli
I vertici di ciascun poligono occupano una colonna di ciascuno di X , Y
X=rand(4,3); Y=rand(4,3); for i=2:3 X(:,i)=X(:,i)+(i-1); % create horizontal offsets for visibility end h=patch(X,Y,'red');
Trama Pseudo 4D
Una matrice (mxn) può essere rappresentata da una superficie usando surf ;
Il colore della superficie viene impostato automaticamente come funzione dei valori nella matrice (mxn) . Se la mappa di colori non è specificata, viene applicata quella predefinita.
È possibile aggiungere una barra di colore per visualizzare la mappa colori corrente e indicare la mappatura dei valori dei dati nella mappa colori.
Nell'esempio seguente, la matrice z (mxn) viene generata dalla funzione:
https://riptutorial.com/it/home 60
z=x.*y.*sin(x).*cos(y);
nell'intervallo [-pi,pi] . Le x ed y valori possono essere generati utilizzando la meshgrid funzione e la superficie è resa come segue:
% Create a Figure figure % Generate the `x` and `y` values in the interval `[-pi,pi]` [x,y] = meshgrid([-pi:.2:pi],[-pi:.2:pi]); % Evaluate the function over the selected interval z=x.*y.*sin(x).*cos(y); % Use surf to plot the surface S=surf(x,y,z); xlabel('X Axis'); ylabel('Y Axis'); zlabel('Z Axis'); grid minor colormap('hot') colorbar
Figura 1
Ora potrebbe essere il caso che ulteriori informazioni siano collegate ai valori della matrice z e che siano archiviate in un'altra matrice (mxn)
È possibile aggiungere queste informazioni aggiuntive sulla trama modificando il modo in cui la superficie è colorata.
Ciò consentirà di avere un tipo di trama 4D: per la rappresentazione 3D della superficie generata dalla prima matrice (mxn) , la quarta dimensione sarà rappresentata dai dati contenuti nella
https://riptutorial.com/it/home 61
seconda matrice (mxn) .
È possibile creare tale trama chiamando surf con 4 input:
surf(x,y,z,C)
dove il parametro C è la seconda matrice (che deve essere della stessa dimensione di z ) e viene utilizzato per definire il colore della superficie.
Nell'esempio seguente, la matrice C viene generata dalla funzione:
C=10*sin(0.5*(x.^2.+y.^2))*33;
nell'intervallo [-pi,pi]
La superficie generata da C è
figura 2
Ora possiamo chiamare surf con quattro input:
figure surf(x,y,z,C) % shading interp xlabel('X Axis'); ylabel('Y Axis'); zlabel('Z Axis'); grid minor colormap('hot')
https://riptutorial.com/it/home 62
colorbar
Figura 3
Confrontando la Figura 1 e la Figura 3, possiamo notare che:
la forma della superficie corrisponde ai valori z (la prima matrice (mxn) )•il colore della superficie (e il suo intervallo, dato dalla barra di colore) corrisponde ai valori C (la prima (mxn) matrice)
•
https://riptutorial.com/it/home 63
Figura 4
Naturalmente, è possibile scambiare z e C nel grafico per avere la forma della superficie data dalla matrice C e il colore dato dalla matrice z :
figure surf(x,y,C,z) % shading interp xlabel('X Axis'); ylabel('Y Axis'); zlabel('Z Axis'); grid minor colormap('hot') colorbar
e confrontare la Figura 2 con la Figura 4
https://riptutorial.com/it/home 64
Disegno veloce
Ci sono tre modi principali per fare sequenze o animazioni sequenziali: plot(x,y) , set(h , 'XData' , y, 'YData' , y) e la linea animatedline . Se vuoi che la tua animazione sia liscia, hai bisogno di un disegno efficiente e i tre metodi non sono equivalenti.
% Plot a sin with increasing phase shift in 500 steps x = linspace(0 , 2*pi , 100); figure tic for thetha = linspace(0 , 10*pi , 500) y = sin(x + thetha); plot(x,y) drawnow end toc
Prendo 5.278172 seconds . La funzione di tracciatura in pratica elimina e ricrea ogni volta l'oggetto linea. Un modo più efficiente per aggiornare un XData YData proprietà XData e YData dell'oggetto Line .
tic h = []; % Handle of line object for thetha = linspace(0 , 10*pi , 500) y = sin(x + thetha); if isempty(h) % If Line still does not exist, create it h = plot(x,y);
https://riptutorial.com/it/home 65
else % If Line exists, update it set(h , 'YData' , y) end drawnow end toc
Ora ottengo 2.741996 seconds , molto meglio!
animatedline è una funzione relativamente nuova, introdotta nel 2014b. Vediamo come va:
tic h = animatedline; for thetha = linspace(0 , 10*pi , 500) y = sin(x + thetha); clearpoints(h) addpoints(h , x , y) drawnow end toc
3.360569 seconds , non buono come l'aggiornamento di un 3.360569 seconds esistente, ma ancora migliore della plot(x,y) .
Naturalmente, se devi tracciare una singola riga, come in questo esempio, i tre metodi sono quasi equivalenti e danno animazioni fluide. Ma se si dispone di grafici più complessi, l'aggiornamento degli oggetti Line esistenti farà la differenza.
Leggi Disegno online: https://riptutorial.com/it/matlab/topic/3978/disegno
https://riptutorial.com/it/home 66
Capitolo 8: Elaborazione delle immagini
Examples
Immagine di base I / O
>> img = imread('football.jpg');
Usa imread per leggere i file di immagine in una matrice in MATLAB. Una volta che hai imread un'immagine, questa viene archiviata come un ND-array in memoria:
>> size(img) ans = 256 320 3
L'immagine 'football.jpg' ha 256 righe e 320 colonne e ha 3 canali di colore: rosso, verde e blu.
Ora puoi specchiarlo:
>> mirrored = img(:, end:-1:1, :); %// like mirroring any ND-array in Matlab
E infine, scriverlo come immagine usando imwrite :
>> imwrite(mirrored, 'mirrored_football.jpg');
Recupera le immagini da Internet
Finché si dispone di una connessione Internet, è possibile leggere le immagini da un collegamento ipertestuale
I=imread('https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png');
Filtro usando un FFT 2D
Come per i segnali 1D, è possibile filtrare le immagini applicando una trasformazione di Fourier, moltiplicando con un filtro nel dominio della frequenza e trasformando nuovamente nel dominio spaziale. Ecco come applicare i filtri passa alto o passa basso a un'immagine con Matlab:
Lascia che l' image sia l' image originale non filtrata, ecco come calcolare la sua FFT 2D:
ft = fftshift(fft2(image));
Ora per escludere una parte dello spettro, è necessario impostare i suoi valori di pixel su 0. La frequenza spaziale contenuta nell'immagine originale viene mappata dal centro verso i bordi (dopo aver usato il fftshift ). Per escludere le basse frequenze, imposteremo l'area circolare centrale
https://riptutorial.com/it/home 67
su 0.
Ecco come generare una maschera binaria a forma di disco con raggio D usando la funzione incorporata:
[x y ~] = size(ft); D = 20; mask = fspecial('disk', D) == 0; mask = imresize(padarray(mask, [floor((x/2)-D) floor((y/2)-D)], 1, 'both'), [x y]);
Mascherare l'immagine del dominio della frequenza può essere fatto moltiplicando il punto FFT in base alla maschera binaria ottenuta sopra:
masked_ft = ft .* mask;
Ora calcoliamo la FFT inversa:
filtered_image = ifft2(ifftshift(masked_ft), 'symmetric');
Le alte frequenze in un'immagine sono i bordi taglienti, quindi questo filtro passa-alto può essere utilizzato per rendere più nitide le immagini.
Filtro delle immagini
Diciamo che hai un'immagine rgbImg , ad esempio, leggi usando imread .
>> rgbImg = imread('pears.png'); >> figure, imshow(rgbImg), title('Original Image')
https://riptutorial.com/it/home 68
Usa fspecial per creare un filtro 2D:
>> h = fspecial('disk', 7); >> figure, imshow(h, []), title('Filter')
Usa l' imfilter per applicare il filtro sull'immagine:
>> filteredRgbImg = imfilter(rgbImg, h); >> figure, imshow(filteredRgbImg), title('Filtered Image')
https://riptutorial.com/it/home 69
Proprietà di misurazione delle regioni collegate
A partire da un'immagine binaria, bwImg , che contiene un numero di oggetti connessi.
>> bwImg = imread('blobs.png'); >> figure, imshow(bwImg), title('Binary Image')
https://riptutorial.com/it/home 70
Per misurare le proprietà (ad es. Area, centroide, ecc.) Di ogni oggetto nell'immagine, utilizzare regionprops :
>> stats = regionprops(bwImg, 'Area', 'Centroid');
stats è un array struct che contiene una struttura per ogni oggetto nell'immagine. L'accesso a una proprietà misurata di un oggetto è semplice. Ad esempio, per visualizzare l'area del primo oggetto, semplicemente,
>> stats(1).Area ans = 35
Visualizza i centroidi dell'oggetto sovrapponendoli sull'immagine originale.
>> figure, imshow(bwImg), title('Binary Image With Centroids Overlaid') >> hold on >> for i = 1:size(stats) scatter(stats(i).Centroid(1), stats(i).Centroid(2), 'filled');
https://riptutorial.com/it/home 71
end
Leggi Elaborazione delle immagini online: https://riptutorial.com/it/matlab/topic/3274/elaborazione-delle-immagini
https://riptutorial.com/it/home 72
Capitolo 9: Errori e errori comuni
Examples
Non nominare una variabile con un nome di funzione esistente
Esiste già una funzione sum() . Di conseguenza, se denominiamo una variabile con lo stesso nome
sum = 1+3;
e se proviamo a usare la funzione mentre la variabile esiste ancora nell'area di lavoro
A = rand(2); sum(A,1)
otterremo l' errore criptico:
Subscript indices must either be real positive integers or logicals.
clear() prima la variabile e poi usa la funzione
clear sum sum(A,1) ans = 1.0826 1.0279
Come possiamo verificare se esiste già una funzione per evitare questo conflitto?
Usa which() con il flag -all :
which sum -all sum is a variable. built-in (C:\Program Files\MATLAB\R2016a\toolbox\matlab\datafun\@double\sum) % Shadowed double method ...
Questo output ci dice che sum è prima una variabile e che i seguenti metodi (funzioni) sono ombreggiati da esso, cioè MATLAB proverà prima ad applicare la nostra sintassi alla variabile, piuttosto che usare il metodo.
Quello che vedi NON è quello che ottieni: char vs cellstring nella finestra di comando
Questo è un esempio di base rivolto ai nuovi utenti. Non si concentra sulla spiegazione della
https://riptutorial.com/it/home 73
differenza tra char e cellstring .
Potrebbe accadere che tu voglia sbarazzarti di ' nelle tue corde, anche se non le hai mai aggiunte. In effetti, quelle sono artefatti che la finestra di comando usa per distinguere tra alcuni tipi.
Una stringa verrà stampata
s = 'dsadasd' s = dsadasd
Una cella stampata verrà stampata
c = {'dsadasd'}; c = 'dsadasd'
Nota come le virgolette singole e il rientro sono artefatti per notificare che c è una cellstring piuttosto che un char . La stringa è infatti contenuta nella cella, cioè
c{1} ans = dsadasd
Gli operatori di trasposizione
.' è il modo corretto di trasporre un vettore o una matrice in MATLAB.•' è il modo corretto di prendere la complessa trasposizione coniugata (aka coniugato di Hermitian) di un vettore o una matrice in MATLAB.
•
Si noti che per la trasposizione .' , c'è un periodo davanti all'apostrofo. Questo è in linea con la sintassi per le altre operazioni basate sull'elemento in MATLAB: * moltiplica le matrici,. .* Moltiplica gli elementi delle matrici insieme. I due comandi sono molto simili, ma concettualmente molto distinti. Come altri comandi MATLAB, questi operatori sono "zucchero sintattico" che viene trasformato in una chiamata di funzione "corretta" in fase di runtime. Proprio come == diventa una valutazione della funzione eq , pensa .' come la scorciatoia per la transpose . Se si scrivesse solo ' (senza il punto), si sta invece utilizzando il comando ctranspose , che calcola la complessa trasposizione del coniugato , che è anche conosciuto come coniugato eremita , spesso usato in fisica. Finché il vettore o la matrice trasposti sono valutati in modo reale, i due operatori producono lo stesso risultato. Ma non appena affronteremo numeri complessi , ci imbatteremo inevitabilmente in problemi se non usiamo la stenografia "corretta". Cosa "corretto" dipende dalla tua applicazione.
Considera il seguente esempio di una matrice C contenente numeri complessi:
>> C = [1i, 2; 3*1i, 4] C =
https://riptutorial.com/it/home 74
0.0000 + 1.0000i 2.0000 + 0.0000i 0.0000 + 3.0000i 4.0000 + 0.0000i
Prendiamo la trasposizione usando la stenografia .' (con il periodo). L'output è come previsto, la forma trasposta di C
>> C.' ans = 0.0000 + 1.0000i 0.0000 + 3.0000i 2.0000 + 0.0000i 4.0000 + 0.0000i
Ora, usiamo ' (senza il punto). Vediamo, che oltre alla trasposizione, i valori complessi sono stati trasformati anche nei loro complessi coniugati .
>> C' ans = 0.0000 - 1.0000i 0.0000 - 3.0000i 2.0000 + 0.0000i 4.0000 + 0.0000i
Per riassumere, se intendi calcolare il coniugato Hermitiano, il complesso coniugato traspone, quindi usa ' (senza il punto). Se vuoi solo calcolare la trasposizione senza complessi coniugando i valori, usa .' (con il periodo).
Funzione non definita o metodo X per gli argomenti di input di tipo Y
Questo è il modo prolisso di MATLAB per dire che non riesce a trovare la funzione che stai cercando di chiamare. Esistono diversi motivi per cui potresti ottenere questo errore:
Quella funzione è stata introdotta dopo la tua attuale versione di MATLAB
La documentazione online di MATLAB fornisce una funzionalità molto utile che consente di determinare in quale versione è stata introdotta una determinata funzione. Si trova in basso a sinistra in ogni pagina della documentazione:
https://riptutorial.com/it/home 75
Confronta questa versione con la tua versione corrente ( ver ) per determinare se questa funzione è disponibile nella tua versione specifica. In caso contrario, prova a cercare le versioni archiviate della documentazione per trovare un'alternativa adatta nella tua versione.
Non hai quella cassetta degli attrezzi!
L'installazione MATLAB di base ha un gran numero di funzioni; tuttavia, le funzionalità più specializzate sono confezionate all'interno di toolbox e vendute separatamente da Mathworks. La documentazione di tutte le toolbox è visibile indipendentemente dal fatto che tu abbia o meno la toolbox, quindi assicurati di controllare e vedere se hai la toolbox appropriata.
Per verificare a quale toolbox appartiene una determinata funzione, guarda in alto a sinistra nella documentazione online per vedere se viene menzionata una toolbox specifica.
https://riptutorial.com/it/home 76
È quindi possibile determinare quali toolbox è stata installata la versione di MATLAB emettendo il comando ver che stamperà un elenco di tutte le toolbox installate.
Se non si dispone di quella cassetta degli attrezzi installata e si desidera utilizzare la funzione, sarà necessario acquistare una licenza per quella particolare casella degli strumenti da The Mathworks.
MATLAB non può localizzare la funzione
Se MATLAB continua a non trovare la tua funzione, allora deve essere una funzione definita dall'utente. È possibile che risieda in un'altra directory e tale directory dovrebbe essere aggiunta al percorso di ricerca per l'esecuzione del codice. È possibile controllare se MATLAB può individuare la funzione utilizzando which che dovrebbe restituire il percorso del file di origine.
Siate consapevoli di inesattezze in virgola mobile
I numeri in virgola mobile non possono rappresentare tutti i numeri reali. Questo è noto come inaccuratezza in virgola mobile.
Esistono infiniti numeri di punti mobili e possono essere infinitamente lunghi (ad es. π ), quindi essere in grado di rappresentarli perfettamente richiederebbe una quantità infinita di memoria. Vedendo questo era un problema, è stata progettata una rappresentazione speciale per l'archiviazione del "numero reale" nel computer, lo standard IEEE 754 . In breve, descrive come i computer memorizzano questo tipo di numeri, con un esponente e una mantissa, come,
floatnum = sign * 2^exponent * mantissa
Con una quantità limitata di bit per ognuno di questi, è possibile ottenere solo una precisione finita. Più piccolo è il numero, più piccolo è il divario tra i possibili numeri (e viceversa!). Puoi provare i tuoi numeri reali in questa demo online .
Essere consapevoli di questo comportamento e cercare di evitare tutti i confronti in virgola mobile e il loro uso come condizioni di arresto nei loop. Vedi sotto due esempi:
Esempi: confronto in virgola mobile eseguito ERRATO:
>> 0.1 + 0.1 + 0.1 == 0.3 ans = logical 0
È una pratica scorretta utilizzare il confronto in virgola mobile come mostrato nell'esempio precedente. Puoi superarlo prendendo il valore assoluto della loro differenza e confrontandolo con un (piccolo) livello di tolleranza.
https://riptutorial.com/it/home 77
Di seguito è riportato un altro esempio, in cui un numero in virgola mobile viene utilizzato come condizione di arresto in un ciclo while: **
k = 0.1; while k <= 0.3 disp(num2str(k)); k = k + 0.1; end % --- Output: --- 0.1 0.2
Manca l'ultimo ciclo previsto ( 0.3 <= 0.3 ).
Esempio: confronto a virgola mobile fatto a DESTRA:
x = 0.1 + 0.1 + 0.1; y = 0.3; tolerance = 1e-10; % A "good enough" tolerance for this case. if ( abs( x - y ) <= tolerance ) disp('x == y'); else disp('x ~= y'); end % --- Output: --- x == y
Diverse cose da notare:
Come previsto, ora x ed y sono trattate come equivalenti.•Nell'esempio sopra, la scelta della tolleranza è stata fatta in modo arbitrario. Pertanto, il valore scelto potrebbe non essere adatto a tutti i casi (specialmente quando si lavora con numeri molto più piccoli). La scelta del legame in modo intelligente può essere effettuata utilizzando la funzione eps , ovvero N*eps(max(x,y)) , dove N è un numero specifico del problema. Una scelta ragionevole per N , che è anche abbastanza permissiva, è 1E2 (anche se, nel problema precedente N=1 sarebbe anche sufficiente).
•
Ulteriori letture:
Consulta queste domande per ulteriori informazioni sull'input di virgola mobile:
Perché il 24.0000 non è uguale a 24.0000 in MATLAB?•La matematica in virgola mobile è rotta?•
Argomenti di input insufficienti
Spesso gli sviluppatori di MATLAB iniziano ad usare l'editor di MATLAB per scrivere e modificare il codice, in particolare le funzioni personalizzate con input e output. C'è un pulsante Esegui in alto
https://riptutorial.com/it/home 78
disponibile nelle versioni recenti di MATLAB:
Quando lo sviluppatore termina con il codice, viene spesso tentato di premere il pulsante Esegui . Per alcune funzioni questo funzionerà bene, ma per gli altri riceveranno un errore di Not enough input arguments e rimarrà perplesso sul motivo per cui si verifica l'errore.
Il motivo per cui questo errore potrebbe non accadere è che hai scritto uno script MATLAB o una funzione che non accetta argomenti di input. L'utilizzo del pulsante Esegui eseguirà uno script di test o eseguirà una funzione senza assumere argomenti di input. Se la tua funzione richiede argomenti di input, l'errore di Not enough input arguments si verificherà quando hai scritto una funzione che si aspetta che gli input entrino nella funzione. Pertanto, non è possibile aspettarsi che la funzione venga eseguita semplicemente premendo il pulsante Esegui .
Per dimostrare questo problema, supponiamo di avere una funzione mult che semplicemente moltiplica due matrici insieme:
function C = mult(A, B) C = A * B; end
Nelle versioni recenti di MATLAB, se hai scritto questa funzione e premuto il pulsante Esegui , ti verrà dato l'errore che ci aspettiamo:
>> mult Not enough input arguments. Error in mult (line 2) C = A * B;
Esistono due modi per risolvere questo problema:
Metodo n. 1 - Tramite il prompt dei comandi
È sufficiente creare gli input necessari nel prompt dei comandi, quindi eseguire la funzione utilizzando gli input che hai creato:
A = rand(5,5); B = rand(5,5); C = mult(A,B);
https://riptutorial.com/it/home 79
Metodo n. 2: interattivo attraverso l'editor
Sotto il pulsante Esegui , c'è una freccia nera scura. Se si fa clic su quella freccia, è possibile specificare le variabili che si desidera ottenere dall'area di lavoro MATLAB digitando il modo in cui si desidera chiamare la funzione esattamente come si è visto nel metodo # 1. Assicurati che le variabili che stai specificando all'interno della funzione esistano nello spazio di lavoro MATLAB:
Fai attenzione alle modifiche alle dimensioni degli array
Alcune operazioni comuni in MATLAB, come la differenziazione o l' integrazione , generano risultati con una quantità di elementi diversa da quella dei dati di input. Questo fatto può essere facilmente trascurato, il che di solito causa errori come le Matrix dimensions must agree . Considera il seguente esempio:
t = 0:0.1:10; % Declaring a time vector y = sin(t); % Declaring a function dy_dt = diff(y); % calculates dy/dt for y = sin(t)
Diciamo che vogliamo tracciare questi risultati. Diamo un'occhiata alle dimensioni dell'array e vediamo:
size(y) is 1x101 size(t) is 1x101
Ma:
size(dy_dt) is 1x100
L'array è un elemento più corto!
Ora immagina di avere dati di misurazione delle posizioni nel tempo e vuoi calcolare jerk (t) , otterrai un array 3 elementi in meno rispetto alla matrice temporale (perché il jerk è la posizione differenziata 3 volte).
vel = diff(y); % calculates velocity vel=dy/dt for y = sin(t) size(vel)=1x100 acc = diff(vel); % calculates acceleration acc=d(vel)/dt size(acc)=1x99 jerk = diff(acc); % calculates jerk jerk=d(acc)/dt size(jerk)=1x98
https://riptutorial.com/it/home 80
E poi operazioni come:
x = jerk .* t; % multiplies jerk and t element wise
restituire errori, perché le dimensioni della matrice non sono d'accordo.
Per calcolare le operazioni come sopra è necessario regolare la dimensione dell'array più grande per adattarla a quella più piccola. Puoi anche eseguire una regressione ( polyfit ) con i tuoi dati per ottenere un polinomio per i tuoi dati.
Errori di mancata corrispondenza delle dimensioni
Gli errori di disallineamento delle dimensioni compaiono in genere quando:
Non prestare attenzione alla forma delle variabili restituite dalle chiamate di funzione / metodo. In molte funzioni MATLAB integrate, le matrici vengono convertite in vettori per accelerare i calcoli e la variabile restituita potrebbe essere ancora un vettore anziché la matrice che ci aspettavamo. Questo è anche uno scenario comune quando è coinvolto il mascheramento logico .
•
Utilizzo di dimensioni di array incompatibili durante il richiamo dell'espansione di array implicita .
•
L'uso di "i" o "j" come unità immaginaria, indici di loop o variabile comune.
Raccomandazione
Poiché i simboli i e j possono rappresentare cose significativamente diverse in MATLAB, il loro uso come indici di loop ha diviso la comunità di utenti di MATLAB da secoli. Mentre alcuni motivi storici di prestazione potrebbero aiutare l'equilibrio ad inclinarsi da un lato, questo non è più il caso e ora la scelta poggia interamente su di te e sulle pratiche di codifica che scegli di seguire.
Le attuali raccomandazioni ufficiali di Mathworks sono:
Poiché i è una funzione, può essere sovrascritta e utilizzata come variabile. Tuttavia, è meglio evitare l'uso di i e j per i nomi di variabili se si intende usarli in aritmetica complessa.
•
Per velocità e robustezza migliorata in aritmetica complessa, usa 1i e 1j invece di i e j .
•
Predefinito
In MATLAB, per impostazione predefinita, le lettere i e j sono nomi di function , che si riferiscono entrambe all'unità immaginaria nel dominio complesso.
Quindi per impostazione predefinita i = j = sqrt(-1) .
https://riptutorial.com/it/home 81
>> i ans = 0.0000 + 1.0000i >> j ans = 0.0000 + 1.0000i
e come dovresti aspettarti:
>> i^2 ans = -1
Usarli come variabile (per indici di loop o altre variabili)
MATLAB consente di utilizzare il nome funzione incorporato come variabile standard. In questo caso il simbolo utilizzato non punterà più alla funzione built-in, ma alla propria variabile definita dall'utente. Questa pratica, tuttavia, non è generalmente raccomandata in quanto può portare a confusione, debugging e manutenzione difficili ( vedi altro esempio do-not-name-a-variable-with-an-existing-function-name ).
Se sei estremamente pedante nel rispettare le convenzioni e le migliori pratiche, eviterai di usarle come indici di loop in questa lingua. Tuttavia, è permesso dal compilatore e perfettamente funzionante, quindi puoi anche scegliere di mantenere le vecchie abitudini e usarle come loop iterator.
>> A = nan(2,3); >> for i=1:2 % perfectly legal loop construction for j = 1:3 A(i, j) = 10 * i + j; end end
Nota che gli indici di loop non escono dall'ambito alla fine del ciclo, quindi mantengono il loro nuovo valore.
>> [ i ; j ] ans = 2 3
Nel caso li usi come variabili, assicurati che siano inizializzati prima di essere usati. Nel ciclo sopra MATLAB inizialo automaticamente quando prepara il ciclo, ma se non inizializzato correttamente puoi vedere rapidamente che potresti inavvertitamente introdurre numeri complex nel tuo risultato.
Se in seguito, è necessario annullare l'ombreggiatura della funzione incorporata (= ad esempio, se si desidera che i e j rappresentino nuovamente l'unità immaginaria), è possibile clear le variabili:
https://riptutorial.com/it/home 82
>> clear i j
Comprendi ora la prenotazione di Mathworks sul loro utilizzo come indici di loop se intendi usarli in operazioni aritmetiche complesse . Il tuo codice sarebbe pieno di inizializzazioni variabili e comandi clear , il modo migliore per confondere il programmatore più serio ( sì, tu! ... ) e gli incidenti del programma che attendono di accadere.
Se non ci si aspetta aritmetica complessa, l'uso di i e j è perfettamente funzionante e non vi è alcuna penalità di prestazioni.
Usandoli come unità immaginaria:
Se il tuo codice ha a che fare con numeri complex , allora i e j torneremo sicuramente utile. Tuttavia, per motivi di disambiguazione e anche per le prestazioni, si consiglia di utilizzare il modulo completo anziché la sintassi abbreviata. La forma completa è 1i (o 1j ).
>> [ i ; j ; 1i ; 1j] ans = 0.0000 + 1.0000i 0.0000 + 1.0000i 0.0000 + 1.0000i 0.0000 + 1.0000i
Rappresentano lo stesso valore sqrt(-1) , ma la forma successiva:
è più esplicito, in un modo semantico.•è più manutenibile (chi guarda il tuo codice in seguito non dovrà leggere il codice per scoprire se i o j fosse una variabile o l'unità immaginaria).
•
è più veloce (fonte: Mathworks).•
Si noti che la sintassi completa 1i è valida con qualsiasi numero che precede il simbolo:
>> a = 3 + 7.8j a = 3.0000 + 7.8000i
Questa è l'unica funzione che puoi inserire con un numero senza un operatore tra di loro.
insidie
Mentre il loro uso come unità immaginaria o variabile OR è perfettamente legale, ecco solo un piccolo esempio di come potrebbe essere confuso se entrambi gli usi si mischiano:
Sovrascriviamo i e ne fanno una variabile:
>> i=3 i =
https://riptutorial.com/it/home 83
3
Ora i è una variabile (mantenendo il valore 3 ), ma abbiamo solo scavalcato la notazione abbreviata dell'unità immaginaria, la forma completa è ancora interpretata correttamente:
>> 3i ans = 0.0000 + 3.0000i
Che ora ci consente di costruire le formulazioni più oscure. Ti lascio valutare la leggibilità di tutti i seguenti costrutti:
>> [ i ; 3i ; 3*i ; i+3i ; i+3*i ] ans = 3.0000 + 0.0000i 0.0000 + 3.0000i 9.0000 + 0.0000i 3.0000 + 3.0000i 12.0000 + 0.0000i
Come puoi vedere, ogni valore nella matrice sopra restituisce un risultato diverso. Sebbene ogni risultato sia valido (ammesso che fosse l'intento iniziale), molti di voi ammetteranno che sarebbe un vero incubo leggere un codice pieno di tali costrutti.
Usando `length` per gli array multidimensionali
Un errore comune che i codificatori MATLAB hanno, sta usando la funzione di length per le matrici (al contrario dei vettori per i quali è stata progettata). La funzione length , come menzionato nella documentazione , " restituisce la lunghezza della dimensione dell'array più grande " dell'input.
Per i vettori, il valore di ritorno della length ha due significati diversi:
Il numero totale di elementi nel vettore.1. La più grande dimensione del vettore.2.
A differenza dei vettori, i valori di cui sopra non sarebbero uguali per gli array di più di una dimensione non singleton (cioè la cui dimensione è maggiore di 1 ). Questo è il motivo per cui l'uso della length per le matrici è ambiguo. Invece, l'utilizzo di una delle seguenti funzioni è incoraggiato, anche quando si lavora con i vettori, per rendere perfettamente chiara l'intenzione del codice:
size(A) - restituisce un vettore di riga i cui elementi contengono la quantità di elementi lungo la corrispondente dimensione di A
1.
numel(A) - restituisce il numero di elementi in A Equivalente a prod(size(A)) .2. ndims(A) - restituisce il numero di dimensioni nell'array A Equivalente al numel(size(A)) .3.
Ciò è particolarmente importante quando si scrivono funzioni di libreria vettorizzate "a prova di futuro", i cui input non sono noti in anticipo e possono avere varie dimensioni e forme.
Leggi Errori e errori comuni online: https://riptutorial.com/it/matlab/topic/973/errori-e-errori-comuni
https://riptutorial.com/it/home 84
Capitolo 10: Funzionalità non documentate
Osservazioni
L'utilizzo di funzionalità non documentate è considerato una pratica rischiosa 1 , in quanto queste funzionalità potrebbero cambiare senza preavviso o semplicemente funzionare in modo diverso su versioni diverse di MATLAB. Per questo motivo, si consiglia di utilizzare tecniche di programmazione difensive come l'inclusione di pezzi di codice non documentati all'interno di blocchi try/catch con fallback documentati.
•
Examples
Funzioni di supporto compatibili con C ++
L'uso di Matlab Coder a volte nega l'uso di alcune funzioni molto comuni, se non sono compatibili con C ++. Relativamente spesso esistono funzioni di supporto non documentate , che possono essere utilizzate come sostituti.
Ecco un elenco completo delle funzioni supportate. .
E seguendo una raccolta di alternative, per le funzioni non supportate:
Le funzioni sprintf e sprintfc sono abbastanza simili, il primo restituisce un array di caratteri , il secondo una stringa di celle :
str = sprintf('%i',x) % returns '5' for x = 5 str = sprintfc('%i',x) % returns {'5'} for x = 5
Tuttavia, sprintfc è compatibile con C ++ supportato da Matlab Coder e sprintf no.
Tracciati 2D con codice colore con dati colore in terza dimensione
Nelle versioni MATLAB precedenti a R2014b , utilizzando il vecchio motore grafico HG1, non era ovvio come creare grafici a linee 2D codificati a colori . Con il rilascio del nuovo motore grafico HG2 è nata una nuova funzionalità non documentata introdotta da Yair Altman :
n = 100; x = linspace(-10,10,n); y = x.^2; p = plot(x,y,'r', 'LineWidth',5); % modified jet-colormap cd = [uint8(jet(n)*255) uint8(ones(n,1))].'; drawnow set(p.Edge, 'ColorBinding','interpolated', 'ColorData',cd)
https://riptutorial.com/it/home 85
Marcatori semi-trasparenti in linea e grafici a dispersione
Dal momento che Matlab R2014b è facilmente possibile ottenere marcatori semitrasparenti per i grafici a linee e a dispersione usando le caratteristiche non documentate introdotte da Yair Altman .
L'idea di base è ottenere l'handle nascosto dei marker e applicare un valore <1 per l'ultimo valore in EdgeColorData per ottenere la trasparenza desiderata.
Qui andiamo per scatter :
%// example data x = linspace(0,3*pi,200); y = cos(x) + rand(1,200); %// plot scatter, get handle h = scatter(x,y); drawnow; %// important %// get marker handle hMarkers = h.MarkerHandle; %// get current edge and face color edgeColor = hMarkers.EdgeColorData faceColor = hMarkers.FaceColorData %// set face color to the same as edge color faceColor = edgeColor; %// opacity opa = 0.3;
https://riptutorial.com/it/home 86
%// set marker edge and face color hMarkers.EdgeColorData = uint8( [edgeColor(1:3); 255*opa] ); hMarkers.FaceColorData = uint8( [faceColor(1:3); 255*opa] );
e per un plot linee
%// example data x = linspace(0,3*pi,200); y1 = cos(x); y2 = sin(x); %// plot scatter, get handle h1 = plot(x,y1,'o-','MarkerSize',15); hold on h2 = plot(x,y2,'o-','MarkerSize',15); drawnow; %// important %// get marker handle h1Markers = h1.MarkerHandle; h2Markers = h2.MarkerHandle; %// get current edge and face color edgeColor1 = h1Markers.EdgeColorData; edgeColor2 = h2Markers.EdgeColorData; %// set face color to the same as edge color faceColor1 = edgeColor1; faceColor2 = edgeColor2; %// opacity opa = 0.3;
https://riptutorial.com/it/home 87
%// set marker edge and face color h1Markers.EdgeColorData = uint8( [edgeColor1(1:3); 255*opa] ); h1Markers.FaceColorData = uint8( [faceColor1(1:3); 255*opa] ); h2Markers.EdgeColorData = uint8( [edgeColor2(1:3); 255*opa] ); h2Markers.FaceColorData = uint8( [faceColor2(1:3); 255*opa] );
Le maniglie dell'indicatore, che sono usate per la manipolazione, sono create con la figura. Il comando drawnow garantisce la creazione della figura prima che vengano richiamati i comandi successivi ed evita errori in caso di ritardi.
Profili di contorno: personalizza le etichette di testo
Quando si visualizzano le etichette sui contorni Matlab non consente di controllare il formato dei numeri, ad esempio per passare alla notazione scientifica.
I singoli oggetti di testo sono normali oggetti di testo, ma il modo in cui li ottieni è non documentato. Puoi accedervi dalla proprietà TextPrims dell'impugnatura del contorno.
figure [X,Y]=meshgrid(0:100,0:100); Z=(X+Y.^2)*1e10; [C,h]=contour(X,Y,Z); h.ShowText='on'; drawnow(); txt = get(h,'TextPrims'); v = str2double(get(txt,'String')); for ii=1:length(v) set(txt(ii),'String',sprintf('%0.3e',v(ii))) end
Nota : è necessario aggiungere un comando drawnow per forzare Matlab a disegnare i contorni, il
https://riptutorial.com/it/home 88
numero e la posizione degli oggetti txt sono determinati solo quando i contorni sono effettivamente disegnati in modo che gli oggetti di testo vengano creati solo allora.
Il fatto che gli oggetti txt vengano creati quando vengono disegnati i contorni significa che vengono ricalcolati ogni volta che la trama viene ridisegnata (ad esempio ridimensionamento della figura). Per gestirlo è necessario ascoltare l' undocumented event MarkedClean :
function customiseContour figure [X,Y]=meshgrid(0:100,0:100); Z=(X+Y.^2)*1e10; [C,h]=contour(X,Y,Z); h.ShowText='on'; % add a listener and call your new format function addlistener(h,'MarkedClean',@(a,b)ReFormatText(a)) end function ReFormatText(h) % get all the text items from the contour t = get(h,'TextPrims'); for ii=1:length(t) % get the current value (Matlab changes this back when it % redraws the plot) v = str2double(get(t(ii),'String')); % Update with the format you want - scientific for example set(t(ii),'String',sprintf('%0.3e',v)); end end
Esempio testato con Matlab r2015b su Windows
Aggiunta / aggiunta di voci a una legenda esistente
https://riptutorial.com/it/home 89
Le leggende esistenti possono essere difficili da gestire. Ad esempio, se la trama ha due linee, ma solo una di esse ha una voce della legenda e che dovrebbe rimanere in questo modo, l'aggiunta di una terza riga con una voce della legenda può essere difficile. Esempio:
figure hold on fplot(@sin) fplot(@cos) legend sin % Add only a legend entry for sin hTan = fplot(@tan); % Make sure to get the handle, hTan, to the graphics object you want to add to the legend
Ora, per aggiungere una voce di legenda per l' tan , ma non per cos , nessuna delle seguenti righe non farà il trucco; falliscono tutti in qualche modo:
legend tangent % Replaces current legend -> fail legend -DynamicLegend % Undocumented feature, adds 'cos', which shouldn't be added -> fail legend sine tangent % Sets cos DisplayName to 'tangent' -> fail legend sine '' tangent % Sets cos DisplayName, albeit empty -> fail legend(f)
Fortunatamente, una proprietà di legenda non documentata chiamata PlotChildren tiene traccia dei figli della figura genitore 1 . Quindi, la strada da percorrere è impostare esplicitamente i figli della legenda attraverso la sua proprietà PlotChildren come segue:
hTan.DisplayName = 'tangent'; % Set the graphics object's display name l = legend; l.PlotChildren(end + 1) = hTan; % Append the graphics handle to legend's plot children
La legenda si aggiorna automaticamente se un oggetto viene aggiunto o rimosso dalla sua proprietà PlotChildren .
1 Infatti: figura. È possibile aggiungere il figlio di qualsiasi figura con la proprietà DisplayName a qualsiasi legenda nella figura, ad esempio da un sottotramma diverso. Questo perché una leggenda di per sé è fondamentalmente un oggetto di assi.
Testato su MATLAB R2016b
Dispersione della trama dispersa
La funzione scatter ha due proprietà non documentate 'jitter' e 'jitterAmount' che consentono di 'jitterAmount' i dati sull'asse x solo. Questo risale a Matlab 7.1 (2005), e forse prima.
Per abilitare questa funzione, impostare la proprietà 'jitter' su 'on' e impostare la proprietà 'jitterAmount' sul valore assoluto desiderato (il valore predefinito è 0.2 ).
Questo è molto utile quando vogliamo visualizzare dati sovrapposti, ad esempio:
scatter(ones(1,10), ones(1,10), 'jitter', 'on', 'jitterAmount', 0.5);
https://riptutorial.com/it/home 90
Maggiori informazioni su Matlab non documentato
Leggi Funzionalità non documentate online: https://riptutorial.com/it/matlab/topic/2383/funzionalita-non-documentate
https://riptutorial.com/it/home 91
Capitolo 11: funzioni
Examples
Esempio di base
Il seguente script MATLAB mostra come definire e chiamare una funzione di base:
myFun.m :
function [out1] = myFun(arg0, arg1) out1 = arg0 + arg1; end
terminale :
>> res = myFun(10, 20) res = 30
Uscite multiple
Il seguente script MATLAB mostra come restituire più output in una singola funzione:
myFun.m :
function [out1, out2, out3] = myFun(arg0, arg1) out1 = arg0 + arg1; out2 = arg0 * arg1; out3 = arg0 - arg1; end
terminale :
>> [res1, res2, res3] = myFun(10, 20) res1 = 30 res2 = 200 res3 = -10
Tuttavia MATLAB restituirà solo il primo valore quando assegnato a una singola variabile
https://riptutorial.com/it/home 92
>> res = myFun(10, 20) res = 30
L'esempio seguente mostra come ottenere un output specifico
>> [~, res] = myFun(10, 20) res = 200
nargin, nargout
Nel corpo di una funzione nargin e nargout indicano rispettivamente il numero effettivo di ingresso e di uscita fornito nella chiamata.
Ad esempio, possiamo controllare l'esecuzione di una funzione in base al numero di input forniti.
myVector.m :
function [res] = myVector(a, b, c) % Roughly emulates the colon operator switch nargin case 1 res = [0:a]; case 2 res = [a:b]; case 3 res = [a:b:c]; otherwise error('Wrong number of params'); end end
terminale:
>> myVector(10) ans = 0 1 2 3 4 5 6 7 8 9 10 >> myVector(10, 20) ans = 10 11 12 13 14 15 16 17 18 19 20 >> myVector(10, 2, 20) ans =
https://riptutorial.com/it/home 93
10 12 14 16 18 20
In modo simile possiamo controllare l'esecuzione di una funzione in base al numero di parametri di output.
myIntegerDivision :
function [qt, rm] = myIntegerDivision(a, b) qt = floor(a / b); if nargout == 2 rm = rem(a, b); end end
terminale :
>> q = myIntegerDivision(10, 7) q = 1 >> [q, r] = myIntegerDivision(10, 7) q = 1 r = 3
Leggi funzioni online: https://riptutorial.com/it/matlab/topic/5659/funzioni
https://riptutorial.com/it/home 94
Capitolo 12: Funzioni di documentazione
Osservazioni
Il testo di aiuto può essere posizionato prima o dopo la linea di function , purché non ci sia codice tra la linea di funzione e l'inizio del testo di aiuto.
•
La maiuscola del nome della funzione mette in grassetto il nome e non è richiesta.•Se una riga è preceduta da See also , qualsiasi nome sulla riga che corrisponde al nome di una classe o funzione sul percorso di ricerca si collegherà automaticamente alla documentazione di quella classe / funzione.
Le funzioni globali possono essere indicate qui precedendo il loro nome con un \ . Altrimenti, i nomi prima tenteranno e risolveranno le funzioni dei membri.
○
•
I collegamenti ipertestuali del modulo <a href="matlab:web('url')">Name</a> sono consentiti.•
Examples
Documentazione di funzioni semplici
function output = mymult(a, b) % MYMULT Multiply two numbers. % output = MYMULT(a, b) multiplies a and b. % % See also fft, foo, sin. % % For more information, see <a href="matlab:web('https://google.com')">Google</a>. output = a * b; end
help mymult fornisce quindi:
mymult Moltiplica due numeri.
output = mymult (a, b) moltiplica a e b.
Vedi anche fft, foo, sin.
Per ulteriori informazioni, consultare Google .
fft e sin si collegano automaticamente al loro rispettivo testo di aiuto e Google è un link a google.com . foo non si collegherà ad alcuna documentazione in questo caso, purché non ci sia una funzione / classe documentata con il nome di foo sul percorso di ricerca.
Documentazione delle funzioni locali
In questo esempio, è possibile accedere alla documentazione della funzione locale baz (definita in foo.m ) tramite il collegamento risultante in help foo o direttamente tramite help foo>baz .
https://riptutorial.com/it/home 95
function bar = foo %This is documentation for FOO. % See also foo>baz % This wont be printed, because there is a line without % on it. end function baz % This is documentation for BAZ. end
Ottenere una firma di funzione
Spesso è utile avere MATLAB stampare il 1 ° linea di una funzione, come questo di solito contiene la firma di funzione, tra cui gli ingressi e le uscite:
dbtype <functionName> 1
Esempio:
>> dbtype fit 1 1 function [fitobj,goodness,output,warnstr,errstr,convmsg] = fit(xdatain,ydatain,fittypeobj,varargin)
Documentare una funzione con uno script di esempio
Per documentare una funzione, è spesso utile avere uno script di esempio che usi la tua funzione. La funzione di pubblicazione in Matlab può quindi essere utilizzata per generare un file di guida con immagini, codice, collegamenti incorporati, ecc. La sintassi per la documentazione del codice può essere trovata qui .
La funzione Questa funzione utilizza un FFT "corretto" in Matlab.
function out_sig = myfft(in_sig) out_sig = fftshift(fft(ifftshift(in_sig))); end
Lo script di esempio Questo è uno script separato che spiega gli input, gli output e fornisce un esempio che spiega perché è necessaria la correzione. Grazie a Wu, Kan, l'autore originale di questa funzione.
%% myfft % This function uses the "proper" fft in matlab. Note that the fft needs to % be multiplied by dt to have physical significance. % For a full description of why the FFT should be taken like this, refer % to: Why_use_fftshift(fft(fftshift(x)))__in_Matlab.pdf included in the % help folder of this code. Additional information can be found: % <https://www.mathworks.com/matlabcentral/fileexchange/25473-why-use-fftshift-fft-fftshift-x----in-matlab-instead-of-fft-x-->
https://riptutorial.com/it/home 96
% %% Inputs % *in_sig* - 1D signal % %% Outputs % *out_sig* - corrected FFT of *in_sig* % %% Examples % Generate a signal with an analytical solution. The analytical solution is % then compared to the fft then to myfft. This example is a modified % version given by Wu, Kan given in the link aboce. %% % Set parameters fs = 500; %sampling frequency dt = 1/fs; %time step T=1; %total time window t = -T/2:dt:T/2-dt; %time grids df = 1/T; %freq step Fmax = 1/2/dt; %freq window f=-Fmax:df:Fmax-df; %freq grids, not used in our examples, could be used by plot(f, X) %% % Generate Gaussian curve Bx = 10; A = sqrt(log(2))/(2*pi*Bx); %Characteristics of Gaussian curve x = exp(-t.^2/2/A^2); %Create Gaussian Curve %% % Generate Analytical solution Xan = A*sqrt(2*pi)*exp(-2*pi^2*f.^2*A^2); %X(f), real part of the analytical Fourier transform of x(t) %% % Take FFT and corrected FFT then compare Xfft = dt *fftshift(fft(x)); %FFT Xfinal = dt * myfft(x); %Corrected FFT hold on plot(f,Xan); plot(f,real(Xfft)); plot(f,real(Xfinal),'ro'); title('Comparison of Corrected and Uncorrected FFT'); legend('Analytical Solution','Uncorrected FFT','Corrected FFT'); xlabel('Frequency'); ylabel('Amplitude'); DT = max(f) - min(f); xlim([-DT/4,DT/4]);
L'output L'opzione di pubblicazione può essere trovata nella scheda "Pubblica", evidenziata nell'immagine Documentazione di funzione semplice di seguito.
Matlab eseguirà lo script e salverà le immagini che vengono visualizzate, nonché il testo generato dalla riga di comando. L'output può essere salvato in diversi tipi di formati, inclusi HTML, Latex e PDF.
L'output dello script di esempio sopra riportato può essere visto nell'immagine qui sotto.
https://riptutorial.com/it/home 97
Leggi Funzioni di documentazione online:
https://riptutorial.com/it/home 98
https://riptutorial.com/it/matlab/topic/1253/funzioni-di-documentazione
https://riptutorial.com/it/home 99
Capitolo 13: Grafica: grafici a linee 2D
Sintassi
plot (Y)•
plot (Y, LineSpec)•
plot (X, Y)•
plot (X, Y, LineSpec)•
trama (X1, Y1, X2, Y2, ..., Xn, Yn)•
grafico (X1, Y1, LineSpec1, X2, Y2, LineSpec2, ..., Xn, Yn, LineSpecn)•
trama (___, nome, valore)•
h = plot (___)•
Parametri
Parametro Dettagli
X valori x
Y valori y
LineSpec Stile della linea, simbolo del marcatore e colore, specificato come una stringa
Nome, Valore
Coppie facoltative di argomenti nome-valore per personalizzare le proprietà della linea
h gestire per allineare l'oggetto grafico
Osservazioni
http://www.mathworks.com/help/matlab/ref/plot.html
Examples
Più linee in un singolo grafico
In questo esempio abbiamo intenzione di tracciare più linee su un singolo asse. Inoltre, scegliamo un aspetto diverso per le linee e creiamo una legenda.
https://riptutorial.com/it/home 100
% create sample data x = linspace(-2,2,100); % 100 linearly spaced points from -2 to 2 y1 = x.^2; y2 = 2*x.^2; y3 = 4*x.^2; % create plot figure; % open new figure plot(x,y1, x,y2,'--', x,y3,'-.'); % plot lines grid minor; % add minor grid title('Quadratic functions with different curvatures'); xlabel('x'); ylabel('f(x)'); legend('f(x) = x^2', 'f(x) = 2x^2', 'f(x) = 4x^2', 'Location','North');
Nell'esempio sopra, abbiamo tracciato le linee con un solo comando- plot . Un'alternativa è usare comandi separati per ogni linea. Dobbiamo tenere il contenuto di una figura tenendo hold on l'ultimo prima di aggiungere la seconda riga. Altrimenti le linee tracciate in precedenza spariranno dalla figura. Per creare lo stesso grafico come sopra, possiamo usare questi seguenti comandi:
figure; hold on; plot(x,y1); plot(x,y2,'--'); plot(x,y3,'-.');
La figura risultante appare così in entrambi i casi:
Linea divisa con NaNs
Interlaccia i tuoi valori y o x con i NaNs
https://riptutorial.com/it/home 101
x = [1:5; 6:10]'; x(3,2) = NaN x = 1 6 2 7 3 NaN 4 9 5 10 plot(x)
Ordini personalizzati di colori e linee
In MATLAB, possiamo impostare nuovi ordini personalizzati di default , come un ordine di colore e uno stile di linea. Ciò significa che verranno applicati nuovi ordini a qualsiasi figura creata dopo aver applicato queste impostazioni. Le nuove impostazioni rimangono fino alla chiusura della sessione MATLAB o alla creazione di nuove impostazioni.
Colore predefinito e ordine di stile della linea
Per impostazione predefinita, MATLAB utilizza un paio di colori diversi e solo uno stile di linea continua. Pertanto, se viene chiamato il plot per disegnare più linee, MATLAB si alterna attraverso un ordine di colore per disegnare linee in diversi colori.
https://riptutorial.com/it/home 102
Possiamo ottenere l'ordine dei colori predefinito chiamando get con un handle globale 0 seguito da questo attributo DefaultAxesColorOrder :
>> get(0, 'DefaultAxesColorOrder') ans = 0 0.4470 0.7410 0.8500 0.3250 0.0980 0.9290 0.6940 0.1250 0.4940 0.1840 0.5560 0.4660 0.6740 0.1880 0.3010 0.7450 0.9330 0.6350 0.0780 0.1840
Colore personalizzato e ordine di stile delle linee
Una volta deciso di impostare un ordine di colore personalizzato e un ordine di stile di linea, MATLAB deve alternarsi in entrambi. Il primo cambiamento che MATLAB applica è un colore. Quando tutti i colori sono esauriti, MATLAB applica lo stile di linea successivo a un ordine di stile di linea definito e imposta un indice di colore su 1. Ciò significa che MATLAB inizierà a alternare nuovamente tutti i colori, ma utilizzando lo stile di linea successivo nel suo ordine. Quando tutti gli stili e i colori delle linee sono esauriti, ovviamente MATLAB inizia a pedalare dall'inizio usando il primo colore e lo stile della prima linea.
Per questo esempio, ho definito un vettore di input e una funzione anonima per semplificare un po 'le figure di plottaggio:
F = @(a,x) bsxfun(@plus, -0.2*x(:).^2, a); x = (-5:5/100:5-5/100)';
https://riptutorial.com/it/home 103
Per impostare un nuovo colore o un nuovo ordine di stile di linea, chiamiamo la funzione set con un handle globale 0 seguito da un attributo DefaultAxesXXXXXXX ; XXXXXXX può essere ColorOrder o LineStyleOrder . Il seguente comando imposta un nuovo ordine di colore su nero, rosso e blu, rispettivamente:
set(0, 'DefaultAxesColorOrder', [0 0 0; 1 0 0; 0 0 1]); plot(x, F([1 2 3 4 5 6],x));
Come puoi vedere, MATLAB si alterna solo attraverso i colori perché l'ordine dello stile di linea è impostato su una linea continua per impostazione predefinita. Quando una serie di colori è esaurita, MATLAB inizia dal primo colore nell'ordine dei colori.
I seguenti comandi impostano sia gli ordini di colore che quelli di stile di linea:
set(0, 'DefaultAxesColorOrder', [0 0 0; 1 0 0; 0 0 1]); set(0, 'DefaultAxesLineStyleOrder', {'-' '--'}); plot(x, F([1 2 3 4 5 6],x));
https://riptutorial.com/it/home 104
Ora, MATLAB si alterna attraverso diversi colori e diversi stili di linea usando il colore come attributo più frequente.
Leggi Grafica: grafici a linee 2D online: https://riptutorial.com/it/matlab/topic/426/grafica--grafici-a-linee-2d
https://riptutorial.com/it/home 105
Capitolo 14: Grafica: trasformazioni 2D e 3D
Examples
Trasformazioni 2D
In questo esempio, prenderemo una linea sagomata in sqaure tracciata usando la line ed eseguiremo delle trasformazioni su di essa. Quindi useremo le stesse trasformazioni ma in ordine diverso e vediamo come influenza i risultati.
Per prima cosa apriamo una figura e impostiamo alcuni parametri iniziali (coordinate punto quadrato e parametri di trasformazione)
%Open figure and create axis Figureh=figure('NumberTitle','off','Name','Transformation Example',... 'Position',[200 200 700 700]); %bg is set to red so we know that we can only see the axes Axesh=axes('XLim',[-8 8],'YLim',[-8,8]); %Initializing Variables square=[-0.5 -0.5;-0.5 0.5;0.5 0.5;0.5 -0.5]; %represented by its vertices Sx=0.5; Sy=2; Tx=2; Ty=2; teta=pi/4;
Quindi costruiamo le matrici di trasformazione (scala, rotazione e traduzione):
%Generate Transformation Matrix S=makehgtform('scale',[Sx Sy 1]); R=makehgtform('zrotate',teta); T=makehgtform('translate',[Tx Ty 0]);
Quindi tracciamo il blu suare:
%% Plotting the original Blue Square OriginalSQ=line([square(:,1);square(1,1)],[square(:,2);square(1,2)],'Color','b','LineWidth',3); grid on; % Applying grid on the figure hold all; % Holding all Following graphs to current axes
Quindi lo tracciamo di nuovo in un colore diverso (rosso) e applichiamo le trasformazioni:
%% Plotting the Red Square %Calculate rectangle vertices HrectTRS=T*R*S; RedSQ=line([square(:,1);square(1,1)],[square(:,2);square(1,2)],'Color','r','LineWidth',3); %transformation of the axes AxesTransformation=hgtransform('Parent',gca,'matrix',HrectTRS); %seting the line to be a child of transformed axes set(RedSQ,'Parent',AxesTransformation);
https://riptutorial.com/it/home 106
Il risultato dovrebbe essere simile a questo:
Ora vediamo cosa succede quando cambiamo l'ordine di trasformazione:
%% Plotting the Green Square HrectRST=R*S*T; GreenSQ=line([square(:,1);square(1,1)],[square(:,2);square(1,2)],'Color','g','LineWidth',3); AxesTransformation=hgtransform('Parent',gca,'matrix',HrectRST); set(GreenSQ,'Parent',AxesTransformation); %% Plotting the Yellow Square HrectSRT=S*R*T; YellowSQ=line([square(:,1);square(1,1)],[square(:,2);square(1,2)],'Color','y','LineWidth',3); AxesTransformation=hgtransform('Parent',gca,'matrix',HrectSRT); set(YellowSQ,'Parent',AxesTransformation);
https://riptutorial.com/it/home 107
Leggi Grafica: trasformazioni 2D e 3D online: https://riptutorial.com/it/matlab/topic/7418/grafica--trasformazioni-2d-e-3d
https://riptutorial.com/it/home 108
Capitolo 15: Imposta le operazioni
Sintassi
C = unione (A, B);1. C = intersezione (A, B);2. C = setdiff (A, B);3. a = ismember (A, x);4.
Parametri
Parametro Dettagli
A, B insiemi, possibilmente matrici o vettori
X possibile elemento di un set
Examples
Operazioni di set elementare
È possibile eseguire operazioni di set elementari con Matlab. Supponiamo di aver dato due vettori o matrici
A = randi([0 10],1,5); B = randi([-1 9], 1,5);
e vogliamo trovare tutti gli elementi che sono in A e in B Per questo possiamo usare
C = intersect(A,B);
C includerà tutti i numeri che fanno parte di A e parte di B Se vogliamo anche trovare la posizione di questi elementi che chiamiamo
[C,pos] = intersect(A,B);
pos è la posizione di questi elementi tale che C == A(pos) .
Un'altra operazione di base è l'unione di due set
D = union(A,B);
Herby contiene D tutti gli elementi di A e B
https://riptutorial.com/it/home 109
Nota che A e B sono considerati come insiemi, il che significa che non importa quante volte un elemento fa parte di A o B Per chiarire questo si può controllare D == union(D,C) .
Se vogliamo ottenere i dati che si trovano in "A" ma non in "B", possiamo usare la seguente funzione
E = setdiff(A,B);
Vogliamo ancora una volta notare che questo è un insieme tale che la seguente affermazione tiene D == union(E,B) .
Supponiamo di voler controllare se
x = randi([-10 10],1,1);
è un elemento di A o B possiamo eseguire il comando
a = ismember(A,x); b = ismember(B,x);
Se a==1 allora x è l'elemento di A e x è nessun elemento è a==0 . Lo stesso vale per B Se a==1 && b==1 x è anche un elemento di C Se a == 1 || b == 1 x è l'elemento di D e se a == 1 || b == 0 è anche un elemento di E
Leggi Imposta le operazioni online: https://riptutorial.com/it/matlab/topic/3242/imposta-le-operazioni
https://riptutorial.com/it/home 110
Capitolo 16: Inizializzazione di matrici o array
introduzione
Matlab ha tre funzioni importanti per creare matrici e impostare i loro elementi a zero, a quelli o alla matrice di identità. (La matrice identità ha quelli sulla diagonale principale e zero altrove).
Sintassi
Z = zeri (sz, datatype, arraytype)•X = ones (sz, datatype)•I = eye (sz, datatype)•
Parametri
Parametro Dettagli
sz n (per una matrice nxn)
sz n, m (per una matrice nxm)
sz m, n, ..., k (per una matrice m-by-n-by -...- by-k)
tipo di dati"double" (predefinito), "single", "int8", "uint8", "int16", "uint16", "int32", "uint32", "int64" o "uint64"
arrayType 'Distribuito'
arrayType 'Codistributed'
arrayType 'GpuArray'
Osservazioni
Queste funzioni creeranno una matrice di doppi, per impostazione predefinita.
Examples
Creazione di una matrice di 0s
z1 = zeros(5); % Create a 5-by-5 matrix of zeroes z2 = zeros(2,3); % Create a 2-by-3 matrix
https://riptutorial.com/it/home 111
Creazione di una matrice di 1 s
o1 = ones(5); % Create a 5-by-5 matrix of ones o2 = ones(1,3); % Create a 1-by-3 matrix / vector of size 3
Creare una matrice di identità
i1 = eye(3); % Create a 3-by-3 identity matrix i2 = eye(5,6); % Create a 5-by-6 identity matrix
Leggi Inizializzazione di matrici o array online: https://riptutorial.com/it/matlab/topic/8049/inizializzazione-di-matrici-o-array
https://riptutorial.com/it/home 112
Capitolo 17: Integrazione
Examples
Integrale, integrale2, integrale3
1 dimensionale
Integrare una funzione monodimensionale
f = @(x) sin(x).^3 + 1;
all'interno dell'intervallo
xmin = 2; xmax = 8;
si può chiamare la funzione
q = integral(f,xmin,xmax);
è anche possibile impostare boundarys per errori relativi e assoluti
q = integral(f,xmin,xmax, 'RelTol',10e-6, 'AbsTol',10-4);
2 dimensioni
Se si vuole integrare una funzione bidimensionale
f = @(x,y) sin(x).^y ;
all'interno dell'intervallo
xmin = 2; xmax = 8; ymin = 1; ymax = 4;
uno chiama la funzione
q = integral2(f,xmin,xmax,ymin,ymax);
Come nell'altro caso è possibile limitare le tolleranze
q = integral2(f,xmin,xmax,ymin,ymax, 'RelTol',10e-6, 'AbsTol',10-4);
https://riptutorial.com/it/home 113
3 dimensionale
Integrando una funzione tridimensionale
f = @(x,y,z) sin(x).^y - cos(z) ;
all'interno dell'intervallo
xmin = 2; xmax = 8; ymin = 1; ymax = 4; zmin = 6; zmax = 13;
viene eseguito chiamando
q = integral3(f,xmin,xmax,ymin,ymax, zmin, zmax);
Di nuovo è possibile limitare le tolleranze
q = integral3(f,xmin,xmax,ymin,ymax, zmin, zmax, 'RelTol',10e-6, 'AbsTol',10-4);
Leggi Integrazione online: https://riptutorial.com/it/matlab/topic/7022/integrazione
https://riptutorial.com/it/home 114
Capitolo 18: Interfacce utente MATLAB
Examples
Passaggio dei dati intorno all'interfaccia utente
Le interfacce utente più avanzate richiedono all'utente di essere in grado di passare informazioni tra le varie funzioni che costituiscono un'interfaccia utente. MATLAB ha un numero di metodi diversi per farlo.
guidata
L' ambiente di sviluppo GUI della MATLAB preferisce utilizzare una struct denominata handles per passare i dati tra i callback. Questa struct contiene tutti gli handle grafici per i vari componenti dell'interfaccia utente, nonché i dati specificati dall'utente. Se non si utilizza un callback creato da GUIDE che passa automaticamente gli handles , è possibile recuperare il valore corrente utilizzando guidata
% hObject is a graphics handle to any UI component in your GUI handles = guidata(hObject);
Se si desidera modificare un valore archiviato in questa struttura dati, è possibile modificarlo, ma è necessario memorizzarlo nuovamente all'interno di hObject affinché le modifiche siano visibili da altri callback. È possibile memorizzarlo specificando un secondo argomento di input per guidata .
% Update the value handles.myValue = 2; % Save changes guidata(hObject, handles)
Il valore di hObject non ha importanza fintanto che si tratta di un componente dell'interfaccia utente all'interno della stessa figure poiché, in definitiva, i dati vengono archiviati nella figura che contiene hObject .
Meglio per:
Memorizzazione della struttura delle handles , in cui è possibile memorizzare tutti gli handle dei componenti della GUI.
•
Memorizzazione di "piccole" altre variabili a cui è necessario accedere tramite la maggior parte delle richiamate.
•
Non consigliato per :
Memorizzazione di variabili di grandi dimensioni a cui non è necessario accedere con tutte le richiamate e le setappdata (utilizzare setappdata / getappdata per queste).
•
https://riptutorial.com/it/home 115
setappdata / getappdata
Simile al guidata approccio, è possibile utilizzare setappdata e getappdata per memorizzare e recuperare i valori all'interno di gestire una grafica. Il vantaggio dell'utilizzo di questi metodi è che è possibile recuperare solo il valore desiderato anziché un'intera struct contenente tutti i dati memorizzati. È simile a un archivio di chiavi / valori.
Per memorizzare i dati all'interno di un oggetto grafico
% Create some data you would like to store myvalue = 2 % Store it using the key 'mykey' setappdata(hObject, 'mykey', myvalue)
E per recuperare lo stesso valore da un callback differente
value = getappdata(hObject, 'mykey');
Nota: se non è stato memorizzato alcun valore prima di chiamare getappdata , verrà restituito un array vuoto ( [] ).
Simile a guidata , i dati sono memorizzati nella figura che contiene hObject .
Meglio per:
Memorizzazione di variabili di grandi dimensioni a cui non è necessario accedere con tutte le richiamate e le sottofunzioni.
•
UserData
Ogni handle grafico ha una proprietà speciale, UserData che può contenere tutti i dati che desideri. Potrebbe contenere un array di celle, una struct o anche uno scalare. È possibile usufruire di questa proprietà e memorizzare in questo campo tutti i dati che si desidera associare a un determinato elemento grafico. È possibile salvare e recuperare il valore utilizzando i metodi get / set standard per gli oggetti grafici o la notazione dei punti se si utilizza R2014b o più recente.
% Create some data to store mydata = {1, 2, 3}; % Store it within the UserData property set(hObject, 'UserData', mydata) % Of if you're using R2014b or newer: % hObject.UserData = mydata;
Quindi dall'interno di un altro callback, è possibile recuperare questi dati:
https://riptutorial.com/it/home 116
their_data = get(hObject, 'UserData'); % Or if you're using R2014b or newer: % their_data = hObject.UserData;
Meglio per:
Memorizzazione di variabili con un ambito limitato (variabili che possono essere utilizzate solo dall'oggetto in cui sono memorizzate o oggetti che hanno una relazione diretta con esso).
•
Funzioni annidate
In MATLAB, una funzione nidificata può leggere e modificare qualsiasi variabile definita nella funzione genitore. In questo modo, se si specifica una richiamata come funzione nidificata, è possibile recuperare e modificare qualsiasi dato memorizzato nella funzione principale.
function mygui() hButton = uicontrol('String', 'Click Me', 'Callback', @callback); % Create a counter to keep track of the number of times the button is clicked nClicks = 0; % Callback function is nested and can therefore read and modify nClicks function callback(source, event) % Increment the number of clicks nClicks = nClicks + 1; % Print the number of clicks so far fprintf('Number of clicks: %d\n', nClicks); end end
Meglio per:
GUI piccole e semplici. (per la prototipazione rapida, per non dover implementare i metodi guidata e / o set/getappdata ).
•
Non consigliato per :
GUI di media, grande o complessa.•
GUI creata con GUIDE .•
Argomenti di input espliciti
Se è necessario inviare dati a una funzione di callback e non è necessario modificare i dati all'interno del callback, è sempre possibile considerare di trasferire i dati al callback utilizzando
https://riptutorial.com/it/home 117
una definizione callback accuratamente predisposta.
Potresti usare una funzione anonima che aggiunge input
% Create some data to send to mycallback data = [1, 2, 3]; % Pass data as a third input to mycallback set(hObject, 'Callback', @(source, event)mycallback(source, event, data))
In alternativa, è possibile utilizzare la sintassi dell'array di celle per specificare un callback, specificando nuovamente input aggiuntivi.
set(hObject, 'Callback', {@mycallback, data})
Meglio per:
Quando il callback necessita di data per eseguire alcune operazioni, la variabile di data non deve essere modificata e salvata in un nuovo stato.
•
Creazione di un pulsante nell'interfaccia utente che sospende l'esecuzione di callback
A volte vorremmo mettere in pausa l'esecuzione del codice per ispezionare lo stato dell'applicazione (vedere Debug ). Quando si esegue il codice tramite l'editor MATLAB, è possibile farlo utilizzando il pulsante "Pausa" nell'interfaccia utente o premendo Ctrl + c (su Windows). Tuttavia, quando un calcolo è stato avviato da una GUI (tramite il callback di alcuni uicontrol ), questo metodo non funziona più e il callback deve essere interrotto tramite un altro callback. Di seguito è una dimostrazione di questo principio:
function interruptibleUI dbclear in interruptibleUI % reset breakpoints in this file figure('Position',[400,500,329,160]); uicontrol('Style', 'pushbutton',... 'String', 'Compute',... 'Position', [24 55 131 63],... 'Callback', @longComputation,... 'Interruptible','on'); % 'on' by default anyway uicontrol('Style', 'pushbutton',... 'String', 'Pause #1',... 'Position', [180 87 131 63],... 'Callback', @interrupt1); uicontrol('Style', 'pushbutton',... 'String', 'Pause #2',... 'Position', [180 12 131 63],... 'Callback', @interrupt2); end
https://riptutorial.com/it/home 118
function longComputation(src,event) superSecretVar = rand(1); pause(15); print('done!'); % we'll use this to determine if code kept running "in the background". end function interrupt1(src,event) % depending on where you want to stop dbstop in interruptibleUI at 27 % will stop after print('done!'); dbstop in interruptibleUI at 32 % will stop after **this** line. end function interrupt2(src,event) % method 2 keyboard; dbup; % this will need to be executed manually once the code stops on the previous line. end
Per assicurarti di aver compreso questo esempio, procedi nel seguente modo:
Incolla il codice sopra in un nuovo file chiamato e salvalo come interruptibleUI.m , in modo tale che il codice inizi sulla prima riga del file (questo è importante perché il 1 ° metodo funzioni).
1.
Esegui lo script.2. Fai clic su Calcola e, poco dopo, fai clic su Pausa n. 1 o Pausa n . 2 .3. Assicurati di poter trovare il valore di superSecretVar .4.
Trasmettere dati in giro usando la struttura "maniglie"
Questo è un esempio di una GUI di base con due pulsanti che modificano un valore memorizzato nella struttura degli handles della GUI.
function gui_passing_data() % A basic GUI with two buttons to show a simple use of the 'handles' % structure in GUI building % Create a new figure. f = figure(); % Retrieve the handles structure handles = guidata(f); % Store the figure handle handles.figure = f; % Create an edit box and two buttons (plus and minus), % and store their handles for future use handles.hedit = uicontrol('Style','edit','Position',[10,200,60,20] , 'Enable', 'Inactive'); handles.hbutton_plus = uicontrol('Style','pushbutton','String','+',... 'Position',[80,200,60,20] , 'Callback' , @ButtonPress); handles.hbutton_minus = uicontrol('Style','pushbutton','String','-',... 'Position',[150,200,60,20] , 'Callback' , @ButtonPress); % Define an initial value, store it in the handles structure and show % it in the Edit box
https://riptutorial.com/it/home 119
handles.value = 1; set(handles.hedit , 'String' , num2str(handles.value)) % Store handles guidata(f, handles); function ButtonPress(hObject, eventdata) % A button was pressed % Retrieve the handles handles = guidata(hObject); % Determine which button was pressed; hObject is the calling object switch(get(hObject , 'String')) case '+' % Add 1 to the value handles.value = handles.value + 1; set(handles.hedit , 'String', num2str(handles.value)) case '-' % Substract 1 from the value handles.value = handles.value - 1; end % Display the new value set(handles.hedit , 'String', num2str(handles.value)) % Store handles guidata(hObject, handles);
Per testare l'esempio, salvarlo in un file chiamato gui_passing_data.m e lanciarlo con F5. Si noti che in un caso così semplice, non è nemmeno necessario memorizzare il valore nella struttura degli handle perché è possibile accedervi direttamente dalla proprietà String della casella di modifica.
Problemi di prestazioni quando si passano dati intorno all'interfaccia utente
Due tecniche principali consentono il passaggio dei dati tra le funzioni della GUI e le callback: setappdata / getappdata e guidata ( leggi di più a riguardo ). Il primo dovrebbe essere usato per variabili più grandi in quanto è più efficiente nel tempo. L'esempio seguente verifica l'efficienza dei due metodi.
Viene creata una GUI con un semplice pulsante e una grande variabile (10000x10000 double) viene memorizzata sia con guidata che con setappdata. Il pulsante ricarica e memorizza la variabile utilizzando i due metodi durante il tempo della loro esecuzione. Il tempo di esecuzione e il miglioramento percentuale usando setappdata vengono visualizzati nella finestra di comando.
function gui_passing_data_performance() % A basic GUI with a button to show performance difference between % guidata and setappdata % Create a new figure. f = figure('Units' , 'normalized'); % Retrieve the handles structure handles = guidata(f);
https://riptutorial.com/it/home 120
% Store the figure handle handles.figure = f; handles.hbutton = uicontrol('Style','pushbutton','String','Calculate','units','normalized',... 'Position',[0.4 , 0.45 , 0.2 , 0.1] , 'Callback' , @ButtonPress); % Create an uninteresting large array data = zeros(10000); % Store it in appdata setappdata(handles.figure , 'data' , data); % Store it in handles handles.data = data; % Save handles guidata(f, handles); function ButtonPress(hObject, eventdata) % Calculate the time difference when using guidata and appdata t_handles = timeit(@use_handles); t_appdata = timeit(@use_appdata); % Absolute and percentage difference t_diff = t_handles - t_appdata; t_perc = round(t_diff / t_handles * 100); disp(['Difference: ' num2str(t_diff) ' ms / ' num2str(t_perc) ' %']) function use_appdata() % Retrieve the data from appdata data = getappdata(gcf , 'data'); % Do something with data % % Store the value again setappdata(gcf , 'data' , data); function use_handles() % Retrieve the data from handles handles = guidata(gcf); data = handles.data; % Do something with data % % Store it back in the handles handles.data = data; guidata(gcf, handles);
Sulla mia Xeon W3530@2,80 GHz ho Difference: 0.00018957 ms / 73 % , quindi usando
https://riptutorial.com/it/home 121
getappdata / setappdata ottengo un miglioramento delle prestazioni del 73%! Si noti che il risultato non cambia se viene utilizzata una variabile doppia 10x10, tuttavia, il risultato cambierà se gli handles contengono molti campi con dati di grandi dimensioni.
Leggi Interfacce utente MATLAB online: https://riptutorial.com/it/matlab/topic/2883/interfacce-utente-matlab
https://riptutorial.com/it/home 122
Capitolo 19: Interpolazione con MATLAB
Sintassi
zy = interp1 (x, y);1. zy = interp1 (x, y, 'metodo');2. zy = interp1 (x, y, 'metodo', 'estrapolazione');3. zy = interp1 (x, y, zx);4. zy = interp1 (x, y, zx, 'metodo');5. zy = interp1 (x, y, zx, 'metodo', 'estrapolazione');6.
Examples
Interpolazione a tratti 2 dimensionale
Inizializziamo i dati:
[X,Y] = meshgrid(1:2:10); Z = X.*cos(Y) - Y.*sin(X);
La superficie appare come la seguente.
Ora impostiamo i punti in cui vogliamo interpolare:
[Vx,Vy] = meshgrid(1:0.25:10);
https://riptutorial.com/it/home 123
Ora possiamo eseguire l'interpolazione più vicina,
Vz = interp2(X,Y,Z,Vx,Vy,'nearest');
interpolazione lineare,
Vz = interp2(X,Y,Z,Vx,Vy,'linear');
https://riptutorial.com/it/home 124
interpolazione cubica
Vz = interp2(X,Y,Z,Vx,Vy,'cubic');
o interpolazione spline:
Vz = interp2(X,Y,Z,Vx,Vy,'spline');
https://riptutorial.com/it/home 125
Interpolazione a tratti 1 dimensionale
Useremo i seguenti dati:
x = 1:5:50; y = randi([-10 10],1,10);
https://riptutorial.com/it/home 126
Con la presente x ed y sono le coordinate dei punti di dati e z sono i punti che hanno bisogno di informazioni circa.
z = 0:0.25:50;
Un modo per trovare i valori y di z è l'interpolazione lineare a tratti.
z_y = interp1(x,y,z,'linear');
https://riptutorial.com/it/home 127
Con la presente si calcola la linea tra due punti adiacenti e si ottiene z_y assumendo che il punto sarebbe un elemento di quelle linee.
interp1 fornisce anche altre opzioni come l'interpolazione più vicina,
z_y = interp1(x,y,z, 'nearest');
https://riptutorial.com/it/home 128
prossima interpolazione,
z_y = interp1(x,y,z, 'next');
interpolazione precedente,
https://riptutorial.com/it/home 129
z_y = interp1(x,y,z, 'previous');
Interpolazione cubica a tratti che preserva la forma,
z_y = interp1(x,y,z, 'pchip');
https://riptutorial.com/it/home 130
convoluzione cubica, z_y = interp1 (x, y, z, 'v5cubic');
e spline interpolazione
z_y = interp1(x,y,z, 'spline');
https://riptutorial.com/it/home 131
Con la presente, interpolazione prossima, successiva e precedente sono parti dell'interpolazione costante.
Interpolazione polinomiale
Inizializziamo i dati che vogliamo interpolare:
x = 0:0.5:10; y = sin(x/2);
Ciò significa che la funzione sottostante per i dati nell'intervallo [0,10] è sinusoidale. Ora vengono calcolati i coefficienti dei polinomiali approssimati:
p1 = polyfit(x,y,1); p2 = polyfit(x,y,2); p3 = polyfit(x,y,3); p5 = polyfit(x,y,5); p10 = polyfit(x,y,10);
In questo caso x è il valore xe y il valore y dei nostri punti dati e il terzo numero è l'ordine / grado del polinomio. Ora impostiamo la griglia su cui vogliamo calcolare la nostra funzione di interpolazione:
zx = 0:0.1:10;
e calcola i valori y:
zy1 = polyval(p1,zx); zy2 = polyval(p2,zx); zy3 = polyval(p3,zx); zy5 = polyval(p5,zx); zy10 = polyval(p10,zx);
Si può vedere che l'errore di approssimazione per il campione si riduce quando aumenta il grado del polinomio.
https://riptutorial.com/it/home 132
Mentre l'approssimazione della linea retta in questo esempio ha errori più grandi, il polinomio dell'ordine 3 approssima la funzione sinusale in questo intervallo relativamente buono.
L'interpolazione con i polinomi dell'ordine 5 e dell'ordine 10 non ha quasi alcun errore di approssimazione.
https://riptutorial.com/it/home 133
Tuttavia, se consideriamo le prestazioni fuori dal campione, si vede che gli ordini troppo alti tendono a sovraffaticare e, quindi, a fare male il campione. Prepariamo
zx = -10:0.1:40; p10 = polyfit(X,Y,10); p20 = polyfit(X,Y,20);
e
zy10 = polyval(p10,zx); zy20 = polyval(p20,zx);
Se osserviamo la trama, vediamo che le prestazioni fuori campione sono le migliori per l'ordine 1
e continua a peggiorare con sempre maggiore intensità.
https://riptutorial.com/it/home 134
Leggi Interpolazione con MATLAB online: https://riptutorial.com/it/matlab/topic/6997/interpolazione-con-matlab
https://riptutorial.com/it/home 135
Capitolo 20: Introduzione all'API MEX
Examples
Controllare il numero di ingressi / uscite in un file MEX C ++
In questo esempio scriveremo un programma di base che controlla il numero di input e output passati a una funzione MEX.
Come punto di partenza, dobbiamo creare un file C ++ che implementa il "gateway MEX". Questa è la funzione eseguita quando il file viene chiamato da MATLAB.
testinputs.cpp
// MathWorks provided header file #include "mex.h" // gateway function void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // This function will error if number of inputs its not 3 or 4 // This function will error if number of outputs is more than 1 // Check inputs: if (nrhs < 3 || nrhs > 4) { mexErrMsgIdAndTxt("Testinputs:ErrorIdIn", "Invalid number of inputs to MEX file."); } // Check outputs: if (nlhs > 1) { mexErrMsgIdAndTxt("Testinputs:ErrorIdOut", "Invalid number of outputs to MEX file."); } }
Innanzitutto, includiamo l'intestazione mex.h che contiene le definizioni di tutte le funzioni e tipi di dati richiesti per funzionare con l'API MEX. Quindi implementiamo la funzione mexFunction come mostrato, dove la sua firma non deve cambiare, indipendentemente dagli input / output effettivamente utilizzati. I parametri della funzione sono i seguenti:
nlhs : numero di uscite richieste.•*plhs[] : Array che contiene tutti gli output nel formato API MEX.•nrhs : numero di input passati.•*prhs[] : Array che contiene tutti gli input nel formato API MEX.•
Successivamente, controlliamo il numero di argomenti input / output, e se la validazione fallisce, viene generato un errore usando la funzione mexErrMsgIdAndTxt (si aspetta somename:iD identificatore di formato somename:iD , un semplice "ID" non funzionerà).
https://riptutorial.com/it/home 136
Una volta che il file è stato compilato come mex testinputs.cpp , la funzione può essere chiamata in MATLAB come:
>> testinputs(2,3) Error using testinputs. Invalid number of inputs to MEX file. >> testinputs(2,3,5) >> [~,~] = testinputs(2,3,3) Error using testinputs. Invalid number of outputs to MEX file.
Inserisci una stringa, modificala in C e stampala
In questo esempio, illustriamo la manipolazione delle stringhe in MATLAB MEX. Creeremo una funzione MEX che accetta una stringa come input da MATLAB, copia i dati in C-string, li modifica e li converte in mxArray restituito al lato MATLAB.
L'obiettivo principale di questo esempio è mostrare come le stringhe possono essere convertite in C / C ++ da MATLAB e viceversa.
stringIO.cpp
#include "mex.h" #include <cstring> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // check number of arguments if (nrhs != 1 || nlhs > 1) { mexErrMsgIdAndTxt("StringIO:WrongNumArgs", "Wrong number of arguments."); } // check if input is a string if (mxIsChar(prhs[0])) { mexErrMsgIdAndTxt("StringIO:TypeError", "Input is not a string"); } // copy characters data from mxArray to a C-style string (null-terminated) char *str = mxArrayToString(prhs[0]); // manipulate the string in some way if (strcmp("theOneString", str) == 0) { str[0] = 'T'; // capitalize first letter } else { str[0] = ' '; // do something else? } // return the new modified string plhs[0] = mxCreateString(str); // free allocated memory mxFree(str); }
Le funzioni rilevanti in questo esempio sono:
https://riptutorial.com/it/home 137
mxIsChar per verificare se un mxArray è di tipo mxCHAR .•mxArrayToString per copiare i dati di una stringa mxArray in un buffer char * .•mxCreateString per creare una stringa mxArray da un char* .•
Come nota a margine, se si desidera solo leggere la stringa e non modificarla, ricordarsi di dichiararla come const char* per velocità e robustezza.
Infine, una volta compilato possiamo chiamarlo da MATLAB come:
>> mex stringIO.cpp >> strOut = stringIO('theOneString') strOut = TheOneString >> strOut = stringIO('somethingelse') strOut= omethingelse
Passa una matrice 3D da MATLAB a C
In questo esempio illustriamo come prendere una doppia matrice 3D di tipo reale da MATLAB e passarla a un double* array C double* .
Gli obiettivi principali di questo esempio sono mostrare come ottenere dati dagli array MATLAB MEX e mettere in evidenza alcuni piccoli dettagli nell'archiviazione e gestione della matrice.
matrixIn.cpp
#include "mex.h" void mexFunction(int nlhs , mxArray *plhs[], int nrhs, mxArray const *prhs[]){ // check amount of inputs if (nrhs!=1) { mexErrMsgIdAndTxt("matrixIn:InvalidInput", "Invalid number of inputs to MEX file."); } // check type of input if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0])){ mexErrMsgIdAndTxt("matrixIn:InvalidType", "Input matrix must be a double, non-complex array."); } // extract the data double const * const matrixAux= static_cast<double const *>(mxGetData(prhs[0])); // Get matrix size const mwSize *sizeInputMatrix= mxGetDimensions(prhs[0]); // allocate array in C. Note: its 1D array, not 3D even if our input is 3D double* matrixInC= (double*)malloc(sizeInputMatrix[0] *sizeInputMatrix[1]
https://riptutorial.com/it/home 138
*sizeInputMatrix[2]* sizeof(double)); // MATLAB is column major, not row major (as C). We need to reorder the numbers // Basically permutes dimensions // NOTE: the ordering of the loops is optimized for fastest memory access! // This improves the speed in about 300% const int size0 = sizeInputMatrix[0]; // Const makes compiler optimization kick in const int size1 = sizeInputMatrix[1]; const int size2 = sizeInputMatrix[2]; for (int j = 0; j < size2; j++) { int jOffset = j*size0*size1; // this saves re-computation time for (int k = 0; k < size0; k++) { int kOffset = k*size1; // this saves re-computation time for (int i = 0; i < size1; i++) { int iOffset = i*size0; matrixInC[i + jOffset + kOffset] = matrixAux[iOffset + jOffset + k]; } } } // we are done! // Use your C matrix here // free memory free(matrixInC); return; }
I concetti rilevanti di cui essere a conoscenza:
Le matrici MATLAB sono tutte 1D in memoria, indipendentemente dal numero di dimensioni che hanno quando vengono utilizzate in MATLAB. Questo vale anche per la maggior parte (se non tutti) la rappresentazione della matrice principale nelle librerie C / C ++, poiché consente l'ottimizzazione e un'esecuzione più rapida.
•
È necessario copiare esplicitamente le matrici da MATLAB a C in un ciclo.•
Le matrici MATLAB sono archiviate nell'ordine delle colonne, come in Fortran, ma C / C ++ e le lingue più moderne sono le righe maggiori. È importante permutare la matrice di input, altrimenti i dati appariranno completamente diversi.
•
Le funzioni rilevanti in questo esempio sono:
mxIsDouble controlla se l'input è di tipo double .•mxIsComplex verifica se l'input è reale o immaginario.•mxGetData restituisce un puntatore ai dati reali nell'array di input. NULL se non ci sono dati reali.•mxGetDimensions restituisce un puntatore a un array mwSize , con la dimensione della •
https://riptutorial.com/it/home 139
dimensione in ogni indice.
Passare una struttura per nome di campo
Questo esempio illustra come leggere le voci struct di tipo vario da MATLAB e passarlo a variabili di tipo C equivalenti.
Mentre è possibile e facile capire dall'esempio come caricare i campi in base ai numeri, è qui ottenuto confrontando i nomi dei campi con le stringhe. Quindi i campi struct possono essere indirizzati con i loro nomi di campo e le variabili in esso possono essere letti da C.
structIn.c
#include "mex.h" #include <string.h> // strcmp void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // helpers double* double_ptr; unsigned int i; // loop variable // to be read variables bool optimal; int randomseed; unsigned int desiredNodes; if (!mxIsStruct(prhs[0])) { mexErrMsgTxt("First argument has to be a parameter struct!"); } for (i=0; i<mxGetNumberOfFields(prhs[0]); i++) { if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"randomseed")) { mxArray *p = mxGetFieldByNumber(prhs[0],0,i); randomseed = *mxGetPr(p); } if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"optimal")) { mxArray *p = mxGetFieldByNumber(prhs[0],0,i); optimal = (bool)*mxGetPr(p); } if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"numNodes")) { mxArray *p = mxGetFieldByNumber(prhs[0],0,i); desiredNodes = *mxGetPr(p); } } }
Il ciclo su i gira su ogni campo nella struttura specificata, mentre le parti if(0==strcmp) confrontano il nome del campo MATLAB con la stringa data. Se è una corrispondenza, il valore corrispondente viene estratto in una variabile C.
Leggi Introduzione all'API MEX online: https://riptutorial.com/it/matlab/topic/680/introduzione-all-api-mex
https://riptutorial.com/it/home 140
Capitolo 21: Lettura di file di grandi dimensioni
Examples
textSCAN
Supponi di avere dati formattati in un file di testo o una stringa di grandi dimensioni, ad es
Data,2015-09-16,15:41:52;781,780.000000,0.0034,2.2345 Data,2015-09-16,15:41:52;791,790.000000,0.1255,96.5948 Data,2015-09-16,15:41:52;801,800.000000,1.5123,0.0043
si può usare textscan per leggerlo abbastanza velocemente. Per fare ciò, ottenere un identificatore di file del file di testo con fopen :
fid = fopen('path/to/myfile');
Supponiamo per i dati in questo esempio, vogliamo ignorare la prima colonna "Dati", leggere la data e l'ora come stringhe e leggere il resto delle colonne come doppi, cioè
Data , 2015-09-16 , 15:41:52;801 , 800.000000 , 1.5123 , 0.0043 ignore string string double double double
Per fare questo, chiama:
data = textscan(fid,'%*s %s %s %f %f %f','Delimiter',',');
L'asterisco in %*s significa "ignora questa colonna". %s significa "interpretare come una stringa". %f significa "interpretare come doppi (float)". Infine, 'Delimiter',',' indica che tutte le virgole devono essere interpretate come il delimitatore tra ogni colonna.
Per riassumere:
fid = fopen('path/to/myfile'); data = textscan(fid,'%*s %s %s %f %f %f','Delimiter',',');
data ora contengono un array di celle con ogni colonna in una cella.
Le stringhe della data e dell'ora sull'array numerico sono veloci
La conversione di stringhe di data e ora in array numerici può essere eseguita con il datenum , anche se può richiedere fino alla metà del tempo di lettura di un file di dati di grandi dimensioni.
Considera i dati nell'esempio Textscan . Di nuovo, usando i testi e interpretando data e ora come
https://riptutorial.com/it/home 141
numeri interi, essi possono essere rapidamente convertiti in un array numerico.
Cioè una riga nei dati di esempio sarebbe interpretata come:
Data , 2015 - 09 - 16 , 15 : 41 : 52 ; 801 , 800.000000 , 1.5123 , 0.0043 ignore double double double double double double double double double double
che sarà letto come:
fid = fopen('path/to/myfile'); data = textscan(fid,'%*s %f %f %f %f %f %f %f %f %f %f','Delimiter',',-:;'); fclose(fid);
Adesso:
y = data{1}; % year m = data{2}; % month d = data{3}; % day H = data{4}; % hours M = data{5}; % minutes S = data{6}; % seconds F = data{7}; % milliseconds % Translation from month to days ms = [0,31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; n = length(y); % Number of elements Time = zeros(n,1); % Declare numeric time array % Algorithm for calculating numeric time array for k = 1:n Time(k) = y(k)*365 + ms(m(k)) + d(k) + floor(y(k)/4)... - floor(y(k)/100) + floor(y(k)/400) + (mod(y(k),4)~=0)... - (mod(y(k),100)~=0) + (mod(y(k),400)~=0)... + (H(k)*3600 + M(k)*60 + S(k) + F(k)/1000)/86400 + 1; end
Usando il datenum su 566.678 elementi richiesti 6,626570 secondi, mentre il metodo sopra richiesto 0,048334 secondi, ovvero lo 0,73% del tempo per il datenum o ~ 137 volte più veloce.
Leggi Lettura di file di grandi dimensioni online: https://riptutorial.com/it/matlab/topic/9023/lettura-di-file-di-grandi-dimensioni
https://riptutorial.com/it/home 142
Capitolo 22: multithreading
Examples
Usare parfor per parallelizzare un loop
Puoi usare parfor per eseguire le iterazioni di un ciclo in parallelo:
Esempio:
poolobj = parpool(2); % Open a parallel pool with 2 workers s = 0; % Performing some parallel Computations parfor i=0:9 s = s + 1; end disp(s) % Outputs '10' delete(poolobj); % Close the parallel pool
Nota: parfor non può essere annidato direttamente. Per parfor nesting usa una funzione in parfor e aggiungi un secondo parfor in quella funzione.
Esempio:
parfor i = 1:n [op] = fun_name(ip); end function [op] = fun_name(ip) parfor j = 1:length(ip) % Some Computation end
Quando usare parfor
Fondamentalmente, il parfor è raccomandato in due casi: molte iterazioni nel tuo loop (es. Come 1e10 ), o se ogni iterazione richiede molto tempo (es. eig(magic(1e4)) ). Nel secondo caso potresti prendere in considerazione l'utilizzo di spmd . La ragione parfor è più lenta di una for ciclo per intervalli brevi o iterazioni veloci è l'overhead necessaria per gestire tutti i lavoratori correttamente, piuttosto che semplicemente eseguire il calcolo.
Anche molte funzioni hanno implicito multithreading incorporato , facendo una parfor ciclo non più efficiente, quando si utilizzano queste funzioni, di una serie for ciclo, poiché vengono già utilizzati tutti i core. in questo caso il parfor sarà effettivamente un danno, poiché ha il sovraccarico di allocazione, pur essendo parallelo come la funzione che si sta tentando di utilizzare.
Considera il seguente esempio per vedere il comportamento di for in contrasto con quello di parfor . Prima apri il pool parallelo se non lo hai già fatto:
https://riptutorial.com/it/home 143
gcp; % Opens a parallel pool using your current settings
Quindi esegui un paio di loop di grandi dimensioni:
n = 1000; % Iteration number EigenValues = cell(n,1); % Prepare to store the data Time = zeros(n,1); for ii = 1:n tic EigenValues{ii,1} = eig(magic(1e3)); % Might want to lower the magic if it takes too long Time(ii,1) = toc; % Collect time after each iteration end figure; % Create a plot of results plot(1:n,t) title 'Time per iteration' ylabel 'Time [s]' xlabel 'Iteration number[-]';
Quindi fai lo stesso con parfor anziché for . Noterai che il tempo medio per iterazione sale. Realizza comunque che il parfor utilizzato tutti i lavoratori disponibili, quindi il tempo totale ( sum(Time) ) deve essere diviso per il numero di core nel tuo computer.
Quindi, mentre il tempo di fare ogni iterazione separata sale usando parfor rispetto a usando for , il tempo totale diminuisce considerevolmente.
Esecuzione di comandi in parallelo usando un'istruzione "Single Program, Multiple Data" (SPMD)
A differenza di un parallelo for-loop ( parfor ), che prende le iterazioni di un ciclo e li distribuisce tra più thread, un singolo programma, più dati ( spmd ), prende una serie di comandi e li distribuisce a tutti i thread, in modo che ciascuno thread esegue il comando e memorizza i risultati. Considera questo:
poolobj = parpool(2); % open a parallel pool with two workers spmd q = rand(3); % each thread generates a unique 3x3 array of random numbers end q{1} % q is called like a cell vector q{2} % the values stored in each thread may be accessed by their index delete(poolobj) % if the pool is closed, then the data in q will no longer be accessible
È importante notare che è possibile accedere a ciascun thread durante il blocco spmd tramite il relativo indice di thread (denominato anche lab index o labindex ):
poolobj = parpool(2); % open a parallel pool with two workers spmd q = rand(labindex + 1); % each thread generates a unique array of random numbers end
https://riptutorial.com/it/home 144
size(q{1}) % the size of q{1} is 2x2 size(q{2}) % the size of q{2} is 3x3 delete(poolobj) % q is no longer accessible
In entrambi gli esempi, q è un oggetto composito , che può essere inizializzato con il comando q = Composite() . È importante notare che gli oggetti compositi sono accessibili solo mentre il pool è in esecuzione.
Utilizzo del comando batch per eseguire vari calcoli in parallelo
Per usare il multi-threading in MATLAB si può usare il comando batch . Si noti che è necessario che la toolbox Parallel Computing sia installata.
Per uno script che richiede molto tempo, ad esempio,
for ii=1:1e8 A(ii)=sin(ii*2*pi/1e8); end
per eseguirlo in modalità batch si usa quanto segue:
job=batch("da")
che consente a MATLAB di funzionare in modalità batch e consente nel frattempo di utilizzare MATLAB per fare altre cose, come aggiungere ulteriori processi batch.
Per recuperare i risultati dopo aver terminato il lavoro e caricare l'array A nell'area di lavoro:
load(job, 'A')
Infine, apri "monitor gui di lavoro" da Home → Ambiente → Parallela → Monitora i lavori ed elimina il lavoro tramite:
delete(job)
Per caricare una funzione per l'elaborazione batch, è sufficiente utilizzare questa istruzione dove fcn è il nome della funzione, N è il numero di matrici di output e x1 , ... , xn sono matrici di input:
j=batch(fcn, N, {x1, x2, ..., xn})
Leggi multithreading online: https://riptutorial.com/it/matlab/topic/4378/multithreading
https://riptutorial.com/it/home 145
Capitolo 23: Per i loop
Osservazioni
Iterare sul vettore di colonna
Una fonte comune di bug sta tentando di eseguire il loop sugli elementi di un vettore di colonna. Un vettore di colonna viene trattato come una matrice con una colonna. (In Matlab non esiste alcuna distinzione.) Il ciclo for viene eseguito una volta con la variabile loop impostata sulla colonna.
% Prints once: [3, 1] my_vector = [1; 2; 3]; for i = my_vector display(size(i)) end
Modifica della variabile di iterazione
La modifica della variabile di iterazione modifica il suo valore per l'iterazione corrente, ma non ha alcun impatto sul suo valore nelle iterazioni successive.
% Prints 1, 2, 3, 4, 5 for i = 1:5 display(i) i = 5; % Fail at trying to terminate the loop end
Prestazione speciale di a:b caso a:b nella parte destra
L'esempio di base tratta 1:n come una normale istanza di creazione di un vettore di riga e quindi iterando su di esso. Per motivi di prestazioni, Matlab tratta in realtà qualsiasi a:b o a:c:b specialmente non creando il vettore riga interamente, ma creando invece ogni elemento uno alla volta.
Questo può essere rilevato modificando leggermente la sintassi.
% Loops forever for i = 1:1e50 end
https://riptutorial.com/it/home 146
% Crashes immediately for i = [1:1e50] end
Examples
Passare da 1 a n
Il caso più semplice consiste nel preformare un task per un numero fisso noto di volte. Diciamo che vogliamo visualizzare i numeri tra 1 e n, possiamo scrivere:
n = 5; for k = 1:n display(k) end
Il ciclo eseguirà l'istruzione interna (s), tutto tra il for e la end , per n volte (5 in questo esempio):
1 2 3 4 5
Ecco un altro esempio:
n = 5; for k = 1:n disp(n-k+1:-1:1) % DISP uses more "clean" way to print on the screen end
questa volta usiamo sia il n che il k nel ciclo, per creare un display "annidato":
5 4 3 2 1 4 3 2 1 3 2 1 2 1 1
Iterare su elementi del vettore
Il lato destro dell'assegnazione in un ciclo for può essere qualsiasi vettore di riga. Il lato sinistro del compito può essere un nome di variabile valido. Il ciclo for assegna un elemento diverso di questo vettore alla variabile ogni corsa.
other_row_vector = [4, 3, 5, 1, 2]; for any_name = other_row_vector
https://riptutorial.com/it/home 147
display(any_name) end
L'output verrebbe visualizzato
4 3 5 1 2
(La versione 1:n è un caso normale, perché in Matlab 1:n è solo sintassi per la costruzione di un vettore di riga di [1, 2, ..., n] .)
Quindi, i due seguenti blocchi di codice sono identici:
A = [1 2 3 4 5]; for x = A disp(x); end
e
for x = 1:5 disp(x); end
E anche i seguenti sono identici:
A = [1 3 5 7 9]; for x = A disp(x); end
e
for x = 1:2:9 disp(x); end
Qualsiasi vettore di riga funzionerà. Non devono essere numeri.
my_characters = 'abcde'; for my_char = my_characters disp(my_char) end
uscirà
a b
https://riptutorial.com/it/home 148
c d e
Iterare su colonne di matrice
Se il lato destro dell'assegnazione è una matrice, in ogni iterazione alla variabile vengono assegnate le successive colonne di questa matrice.
some_matrix = [1, 2, 3; 4, 5, 6]; % 2 by 3 matrix for some_column = some_matrix display(some_column) end
(La versione vettoriale riga è un caso normale di questo, perché in Matlab un vettore riga è solo una matrice le cui colonne sono la dimensione 1.)
L'output verrebbe visualizzato
1 4 2 5 3 6
cioè ogni colonna della matrice iterata visualizzata, ogni colonna stampata su ogni chiamata di display .
Loop over indexes
my_vector = [0, 2, 1, 3, 9]; for i = 1:numel(my_vector) my_vector(i) = my_vector(i) + 1; end
Le operazioni più semplici eseguite con i cicli for possono essere eseguite più rapidamente e più facilmente dalle operazioni vettorializzate. Ad esempio, il ciclo precedente può essere sostituito da my_vector = my_vector + 1 .
Cicli annidati
I loop possono essere annidati, per preformare l'attività iterata all'interno di un'altra attività iterata. Considera i seguenti cicli:
ch = 'abc'; m = 3; for c = ch for k = 1:m disp([c num2str(k)]) % NUM2STR converts the number stored in k to a charachter, % so it can be concataneted with the letter in c
https://riptutorial.com/it/home 149
end end
usiamo 2 iteratori per visualizzare tutte le combinazioni di elementi da abc e 1:m , che produce:
a1 a2 a3 b1 b2 b3 c1 c2 c3
Possiamo anche utilizzare cicli annidati per combinare le attività da svolgere ogni volta e le attività da eseguire una volta in più iterazioni:
N = 10; n = 3; a1 = 0; % the first element in Fibonacci series a2 = 1; % the secound element in Fibonacci series for j = 1:N for k = 1:n an = a1 + a2; % compute the next element in Fibonacci series a1 = a2; % save the previous element for the next iteration a2 = an; % save ht new element for the next iteration end disp(an) % display every n'th element end
Qui vogliamo calcolare tutte le serie di Fibonacci , ma mostrare ogni volta solo il n elemento, quindi otteniamo
3 13 55 233 987 4181 17711 75025 317811 1346269
Un'altra cosa che possiamo fare è usare il primo iteratore (esterno) all'interno del ciclo interno. Ecco un altro esempio:
N = 12; gap = [1 2 3 4 6]; for j = gap for k = 1:j:N fprintf('%d ',k) % FPRINTF prints the number k proceeding to the next the line end fprintf('\n') % go to the next line
https://riptutorial.com/it/home 150
end
Questa volta usiamo il ciclo annidato per formattare l'output e freniamo la linea solo quando è stato introdotto un nuovo spazio ( j ) tra gli elementi. Passiamo attraverso la larghezza del gap nel loop esterno e lo usiamo all'interno del loop interno per scorrere il vettore:
1 2 3 4 5 6 7 8 9 10 11 12 1 3 5 7 9 11 1 4 7 10 1 5 9 1 7
Avviso: strani loop con lo stesso contatore.
Questo non è qualcosa che vedrai in altri ambienti di programmazione. L'ho incontrato qualche anno fa e non riuscivo a capire perché stava succedendo, ma dopo aver lavorato con MATLAB per un po 'sono riuscito a capirlo. Guarda il frammento di codice qui sotto:
for x = 1:10 for x = 1:10 fprintf('%d,', x); end fprintf('\n'); end
non ti aspetteresti che funzioni correttamente ma lo fa, producendo il seguente output:
1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10,
Il motivo è che, come per tutto il resto in MATLAB, anche il contatore x è una matrice, un vettore per la precisione. In quanto tale, x è solo un riferimento a un 'array' (una struttura di memoria coerente e consecutiva) che è opportunamente referenziato con ogni ciclo conseguente (nidificato o non). Il fatto che il ciclo annidato utilizzi lo stesso identificatore non fa alcuna differenza sul modo in cui i valori di quell'array sono referenziati. L'unico problema è che all'interno del ciclo annidato la x esterna è nascosta dal nidificato (locale) x e quindi non può essere referenziata. Tuttavia, la funzionalità della struttura del ciclo nidificata rimane intatta.
Leggi Per i loop online: https://riptutorial.com/it/matlab/topic/1927/per-i-loop
https://riptutorial.com/it/home 151
Capitolo 24: Prestazioni e Benchmarking
Osservazioni
Il codice di profilazione è un modo per evitare la temuta pratica di " ottimizzazione prematura ", concentrando lo sviluppatore su quelle parti del codice che effettivamente giustificano gli sforzi di ottimizzazione.
•
Articolo della documentazione di MATLAB intitolato " Misura le prestazioni del tuo programma ".
•
Examples
Identificazione dei colli di bottiglia delle prestazioni utilizzando il Profiler
Il MATLAB Profiler è uno strumento per la profilazione software del codice MATLAB. Usando il Profiler, è possibile ottenere una rappresentazione visiva del tempo di esecuzione e del consumo di memoria.
L'esecuzione di Profiler può essere eseguita in due modi:
Facendo clic sul pulsante "Esegui e ora" nella GUI MATLAB mentre si ha un file .m aperto nell'editor (aggiunto in R2012b ).
•
Programmaticamente, utilizzando:
profile on <some code we want to test> profile off
•
Di seguito sono riportati alcuni esempi di codice e il risultato della sua profilazione:
function docTest for ind1 = 1:100 [~] = var(... sum(... randn(1000))); end spy
https://riptutorial.com/it/home 152
Da quanto sopra, apprendiamo che la funzione spy impiega circa il 25% del tempo totale di esecuzione. Nel caso del "codice reale", una funzione che richiede una percentuale così elevata del tempo di esecuzione sarebbe un buon candidato per l'ottimizzazione, al contrario delle funzioni analoghe a var e cla cui ottimizzazione dovrebbe essere evitata.
Inoltre, è possibile fare clic sulle voci nella colonna Nome funzione per visualizzare un'analisi dettagliata del tempo di esecuzione per quella voce. Ecco l'esempio di clic spy :
https://riptutorial.com/it/home 153
È anche possibile profilare il consumo di memoria eseguendo il profile('-memory') prima di eseguire il Profiler.
https://riptutorial.com/it/home 154
Confronto del tempo di esecuzione di più funzioni
La combinazione ampiamente utilizzata di tic e toc può fornire un'idea approssimativa del tempo di esecuzione di una funzione o di snippet di codice.
Per confrontare parecchie funzioni non dovrebbe essere usato. Perché? È quasi impossibile fornire condizioni uguali per tutti i frammenti di codice da confrontare all'interno di uno script utilizzando la soluzione di cui sopra. Forse le funzioni condividono lo stesso spazio di funzione e le variabili comuni, quindi in seguito chiamate funzioni e frammenti di codice già sfruttano le variabili e le funzioni precedentemente inizializzate. Inoltre, non vi è alcuna idea se il compilatore JIT gestisca allo stesso modo questi snippet chiamati successivamente.
La funzione dedicata per i benchmark è timeit . L'esempio seguente illustra il suo uso.
Ci sono la matrice A e la matrice B Dovrebbe essere determinato quale riga di B è la più simile ad A
https://riptutorial.com/it/home 155
contando il numero di elementi diversi.
function t = bench() A = [0 1 1 1 0 0]; B = perms(A); % functions to compare fcns = { @() compare1(A,B); @() compare2(A,B); @() compare3(A,B); @() compare4(A,B); }; % timeit t = cellfun(@timeit, fcns); end function Z = compare1(A,B) Z = sum( bsxfun(@eq, A,B) , 2); end function Z = compare2(A,B) Z = sum(bsxfun(@xor, A, B),2); end function Z = compare3(A,B) A = logical(A); Z = sum(B(:,~A),2) + sum(~B(:,A),2); end function Z = compare4(A,B) Z = pdist2( A, B, 'hamming', 'Smallest', 1 ); end
Questo metodo di riferimento è stato visto per la prima volta in questa risposta .
Va bene essere "single"!
Panoramica:
Il tipo di dati predefinito per gli array numerici in MATLAB è double . double è una rappresentazione in virgola mobile di numeri e questo formato richiede 8 byte (o 64 bit) per valore. In alcuni casi, dove ad esempio si tratta solo di numeri interi o quando l'instabilità numerica non è un problema imminente, una tale profondità di bit potrebbe non essere richiesta. Per questo motivo, si consiglia di considerare i vantaggi della precisione single (o di altri tipi appropriati):
Tempi di esecuzione più rapidi (particolarmente evidenti sulle GPU).•Metà del consumo di memoria: può riuscire dove il double fallisce a causa di un errore di memoria insufficiente; più compatto quando si archiviano come file.
•
La conversione di una variabile da qualsiasi tipo di dati supportato a single viene eseguita utilizzando:
sing_var = single(var);
https://riptutorial.com/it/home 156
Alcune funzioni di uso comune (come: zeros , eye , ones , etc. ) che di uscita double valori di default, permettono specificando il tipo / classe dell'uscita.
Conversione di variabili in uno script in una precisione / tipo / classe non predefinita:
A partire da luglio 2016, non esiste alcun modo documentato per modificare il tipo di dati MATLAB predefinito da double .
In MATLAB, le nuove variabili di solito imitano i tipi di dati delle variabili utilizzate durante la loro creazione. Per illustrare questo, considera il seguente esempio:
A = magic(3); B = diag(A); C = 20*B; >> whos C Name Size Bytes Class Attributes C 3x1 24 double
A = single(magic(3)); % A is converted to "single" B = diag(A); C = B*double(20); % The stricter type, which in this case is "single", prevails D = single(size(C)); % It is generally advised to cast to the desired type explicitly. >> whos C Name Size Bytes Class Attributes C 3x1 12 single
Pertanto, può sembrare sufficiente eseguire il cast / convertire più variabili iniziali per far sì che il cambiamento permei attraverso il codice, tuttavia ciò è scoraggiato (vedere Caveat & Pitfalls di seguito).
Avvertenze e insidie:
Le conversioni ripetute sono scoraggiate a causa dell'introduzione del rumore numerico (quando si esegue il cast da single a double ) o della perdita di informazioni (quando si esegue il cast da double a single o tra determinati tipi di interi ), ad esempio:
double(single(1.2)) == double(1.2) ans = 0
Questo può essere in qualche modo mitigato usando typecast . Vedi anche Sii consapevole dell'imprecisione di virgola mobile .
1.
Affidarsi esclusivamente alla tipizzazione implicita dei dati (cioè quale MATLAB indovina il tipo di output di un calcolo dovrebbe essere) è scoraggiato a causa di diversi effetti indesiderati che potrebbero sorgere:
2.
https://riptutorial.com/it/home 157
Perdita di informazioni : quando è previsto un double risultato, ma una combinazione incurante di operandi single e double produce single precisione single .
•
Consumo di memoria inaspettatamente alto : quando è previsto un single risultato ma un calcolo disattento genera una double uscita.
•
Overhead non necessario quando si lavora con GPU : quando si mischiano i tipi gpuArray (cioè le variabili memorizzate in VRAM) con variabili non gpuArray (cioè quelle normalmente memorizzate nella RAM) i dati dovranno essere trasferiti in un modo o nell'altro prima che il calcolo possa essere eseguito. Questa operazione richiede tempo e può essere molto evidente nei calcoli ripetitivi.
•
Errori durante la miscelazione di tipi in virgola mobile con tipi interi : funzioni come mtimes ( * ) non sono definite per gli input misti di tipi interi e in virgola mobile e si verificheranno errori. Funzioni come times ( .* ) Non sono affatto definite per gli input di tipo intero e si ripeteranno di nuovo.
>> ones(3,3,'int32')*ones(3,3,'int32') Error using * MTIMES is not fully supported for integer classes. At least one input must be scalar. >> ones(3,3,'int32').*ones(3,3,'double') Error using .* Integers can only be combined with integers of the same class, or scalar doubles.
•
Per una migliore leggibilità del codice e una riduzione del rischio di tipi indesiderati, si consiglia un approccio difensivo, in cui le variabili vengono espresse espressamente per il tipo desiderato.
Guarda anche:
Documentazione MATLAB: numeri a virgola mobile .•Articolo tecnico di Mathworks: best practice per la conversione del codice MATLAB in punto fisso .
•
riorganizzare un array ND può migliorare le prestazioni generali
In alcuni casi è necessario applicare le funzioni a un set di ND-array. Diamo un'occhiata a questo semplice esempio.
A(:,:,1) = [1 2; 4 5]; A(:,:,2) = [11 22; 44 55]; B(:,:,1) = [7 8; 1 2]; B(:,:,2) = [77 88; 11 22]; A = ans(:,:,1) =
https://riptutorial.com/it/home 158
1 2 4 5 ans(:,:,2) = 11 22 44 55 >> B B = ans(:,:,1) = 7 8 1 2 ans(:,:,2) = 77 88 11 22
Entrambe le matrici sono 3D, diciamo che dobbiamo calcolare quanto segue:
result= zeros(2,2); ... for k = 1:2 result(i,j) = result(i,j) + abs( A(i,j,k) - B(i,j,k) ); ... if k is very large, this for-loop can be a bottleneck since MATLAB order the data in a column major fashion. So a better way to compute "result" could be: % trying to exploit the column major ordering Aprime = reshape(permute(A,[3,1,2]), [2,4]); Bprime = reshape(permute(B,[3,1,2]), [2,4]); >> Aprime Aprime = 1 4 2 5 11 44 22 55 >> Bprime Bprime = 7 1 8 2 77 11 88 22
Ora sostituiamo il ciclo precedente per quanto segue:
result= zeros(2,2); .... temp = abs(Aprime - Bprime); for k = 1:2 result(i,j) = result(i,j) + temp(k, i+2*(j-1)); ...
https://riptutorial.com/it/home 159
Abbiamo riorganizzato i dati in modo da poter sfruttare la memoria cache. La permutazione e la rimodellazione possono essere costose, ma quando si lavora con array ND di grandi dimensioni, il costo computazionale relativo a queste operazioni è molto più basso rispetto al lavoro con gli array non organizzati.
L'importanza della preallocazione
Gli array in MATLAB sono conservati come blocchi continui in memoria, allocati e rilasciati automaticamente da MATLAB. MATLAB nasconde le operazioni di gestione della memoria come il ridimensionamento di una matrice dietro la sintassi facile da usare:
a = 1:4 a = 1 2 3 4 a(5) = 10 % or alternatively a = [a, 10] a = 1 2 3 4 10
È importante capire che quanto sopra non è un'operazione banale, a(5) = 10 causerà MATLAB per allocare un nuovo blocco di memoria di dimensione 5, copiare i primi 4 numeri e impostare il 5'th a 10. Questa è un'operazione O(numel(a)) e non O(1) .
Considera quanto segue:
clear all n=12345678; a=0; tic for i = 2:n a(i) = sqrt(a(i-1)) + i; end toc Elapsed time is 3.004213 seconds.
a è riallocato n volte in questo ciclo (escludendo alcune ottimizzazioni intraprese da MATLAB)! Nota che MATLAB ci dà un avvertimento:
"La variabile 'a' sembra cambiare dimensione ad ogni iterazione del ciclo. Prendi in considerazione la preallocazione per la velocità."
Cosa succede quando preassegniamo?
a=zeros(1,n); tic for i = 2:n a(i) = sqrt(a(i-1)) + i; end
https://riptutorial.com/it/home 160
toc Elapsed time is 0.410531 seconds.
Possiamo vedere che il runtime è ridotto di un ordine di grandezza.
Metodi per la preallocazione:
MATLAB offre varie funzioni per l'assegnazione di vettori e matrici, a seconda delle esigenze specifiche dell'utente. Questi includono: zeros , ones , nan , eye , true ecc.
a = zeros(3) % Allocates a 3-by-3 matrix initialized to 0 a = 0 0 0 0 0 0 0 0 0 a = zeros(3, 2) % Allocates a 3-by-2 matrix initialized to 0 a = 0 0 0 0 0 0 a = ones(2, 3, 2) % Allocates a 3 dimensional array (2-by-3-by-2) initialized to 1 a(:,:,1) = 1 1 1 1 1 1 a(:,:,2) = 1 1 1 1 1 1 a = ones(1, 3) * 7 % Allocates a row vector of length 3 initialized to 7 a = 7 7 7
Un tipo di dati può anche essere specificato:
a = zeros(2, 1, 'uint8'); % allocates an array of type uint8
È anche facile clonare le dimensioni di un array esistente:
a = ones(3, 4); % a is a 3-by-4 matrix of 1's b = zeros(size(a)); % b is a 3-by-4 matrix of 0's
E clona il tipo:
a = ones(3, 4, 'single'); % a is a 3-by-4 matrix of type single b = zeros(2, 'like', a); % b is a 2-by-2 matrix of type single
https://riptutorial.com/it/home 161
nota che "come" clona anche la complessità e la scarsità .
La preallocazione viene raggiunta implicitamente utilizzando qualsiasi funzione che restituisce un array della dimensione finale richiesta, come rand , gallery , kron , bsxfun , colon e molti altri. Ad esempio, un modo comune per allocare vettori con elementi che variano linearmente è usando l'operatore colon (con la variante 1 o 3-operando 1 ):
a = 1:3 a = 1 2 3 a = 2:-3:-4 a = 2 -1 -4
Gli array di celle possono essere allocati usando la funzione cell() allo stesso modo degli zeros() .
a = cell(2,3) a = [] [] [] [] [] []
Nota che gli array di celle funzionano tenendo puntatori alle posizioni in memoria del contenuto delle celle. Quindi tutti i suggerimenti per la preallazione si applicano anche agli elementi del singolo array di celle.
Ulteriori letture:
Documentazione ufficiale di MATLAB su " Preallocare memoria ".•Documentazione ufficiale di MATLAB su " Come MATLAB assegna memoria ".•Prestazioni di preallocazione su matlab non documentato .•Comprendere la preallocazione delle matrici su Loren sull'arte di MATLAB•
Leggi Prestazioni e Benchmarking online: https://riptutorial.com/it/matlab/topic/1141/prestazioni-e-benchmarking
https://riptutorial.com/it/home 162
Capitolo 25: Programmazione orientata agli oggetti
Examples
Definire una classe
Una classe può essere definita usando classdef in un file .m con lo stesso nome della classe. Il file può contenere il classdef ... blocco end e funzioni locali da utilizzare nei metodi di classe.
La definizione di classe MATLAB più generale ha la seguente struttura:
classdef (ClassAttribute = expression, ...) ClassName < ParentClass1 & ParentClass2 & ... properties (PropertyAttributes) PropertyName end methods (MethodAttributes) function obj = methodName(obj,arg2,...) ... end end events (EventAttributes) EventName end enumeration EnumName end end
Documentazione MATLAB: attributi di classe , attributi di proprietà , attributi di metodo , attributi di eventi , restrizioni di classe di enumerazione .
Classe di esempio:
Una classe chiamata Car può essere definita nel file Car.m as
classdef Car < handle % handle class so properties persist properties make model mileage = 0; end methods function obj = Car(make, model) obj.make = make;
https://riptutorial.com/it/home 163
obj.model = model; end function drive(obj, milesDriven) obj.mileage = obj.mileage + milesDriven; end end end
Si noti che il costruttore è un metodo con lo stesso nome della classe. <Un costruttore è un metodo speciale di una classe o di una struttura in programmazione orientata agli oggetti che inizializza un oggetto di quel tipo. Un costruttore è un metodo di istanza che di solito ha lo stesso nome della classe e può essere utilizzato per impostare i valori dei membri di un oggetto, sia a valori predefiniti che a valori definiti dall'utente.>
Un'istanza di questa classe può essere creata chiamando il costruttore;
>> myCar = Car('Ford', 'Mustang'); //creating an instance of car class
Chiamando il metodo di drive aumenterà il chilometraggio
>> myCar.mileage ans = 0 >> myCar.drive(450); >> myCar.mileage ans = 450
Classi Value vs Handle
Le classi in MATLAB sono divise in due categorie principali: classi di valore e classi di handle. La principale differenza è che quando si copia un'istanza di una classe di valore, i dati sottostanti vengono copiati nella nuova istanza, mentre per le classi di handle la nuova istanza punta ai dati originali e la modifica dei valori nella nuova istanza li modifica nell'originale. Una classe può essere definita come un handle ereditando dalla classe handle .
classdef valueClass properties data end end
e
classdef handleClass < handle properties data end
https://riptutorial.com/it/home 164
end
poi
>> v1 = valueClass; >> v1.data = 5; >> v2 = v1; >> v2.data = 7; >> v1.data ans = 5 >> h1 = handleClass; >> h1.data = 5; >> h2 = h1; >> h2.data = 7; >> h1.data ans = 7
Ereditando da classi e classi astratte
Dichiarazione di non responsabilità: gli esempi presentati qui hanno lo scopo di mostrare l'uso di classi astratte ed ereditarietà e potrebbero non essere necessariamente di uso pratico. Inoltre, non c'è alcuna cosa come polimorfica in MATLAB e quindi l'uso di classi astratte è limitato. Questo esempio è per mostrare a chi creare una classe, ereditare da un'altra classe e applicare una classe astratta per definire un'interfaccia comune.
L'uso di classi astratte è piuttosto limitato in MATLAB ma può ancora venire utile in un paio di occasioni.
Diciamo che vogliamo un registratore di messaggi. Potremmo creare una classe simile a quella seguente:
classdef ScreenLogger properties(Access=protected) scrh; end methods function obj = ScreenLogger(screenhandler) obj.scrh = screenhandler; end function LogMessage(obj, varargin) if ~isempty(varargin) varargin{1} = num2str(varargin{1}); fprintf(obj.scrh, '%s\n', sprintf(varargin{:})); end end end end
Proprietà e metodi
https://riptutorial.com/it/home 165
In breve, le proprietà mantengono uno stato di un oggetto mentre i metodi sono come l'interfaccia e definiscono le azioni sugli oggetti.
La proprietà scrh è protetta. Questo è il motivo per cui deve essere inizializzato in un costruttore. Esistono altri metodi (getter) per accedere a questa proprietà, ma questo non è all'altezza di questo esempio. Proprietà e metodi possono essere accessibili tramite una variabile che contiene un riferimento a un oggetto utilizzando la notazione punto seguita da un nome di un metodo o una proprietà:
mylogger = ScreenLogger(1); % OK mylogger.LogMessage('My %s %d message', 'very', 1); % OK mylogger.scrh = 2; % ERROR!!! Access denied
Proprietà e metodi possono essere pubblici, privati o protetti. In questo caso, protetto significa che sarò in grado di accedere a scrh da una classe ereditata ma non dall'esterno. Di default tutte le proprietà e i metodi sono pubblici. Pertanto, LogMessage() può essere utilizzato liberamente al di fuori della definizione della classe. Anche LogMessage definisce un'interfaccia che significa che questo è ciò che dobbiamo chiamare quando vogliamo che un oggetto registri i nostri messaggi personalizzati.
Applicazione
Diciamo che ho uno script in cui utilizzo il mio logger:
clc; % ... a code logger = ScreenLogger(1); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something');
Se ho più posti dove utilizzo lo stesso logger e poi voglio cambiarlo in qualcosa di più sofisticato, come scrivere un messaggio in un file, dovrei creare un altro oggetto:
classdef DeepLogger properties(SetAccess=protected) FileName end methods function obj = DeepLogger(filename) obj.FileName = filename; end function LogMessage(obj, varargin) if ~isempty(varargin) varargin{1} = num2str(varargin{1}); fid = fopen(obj.fullfname, 'a+t'); fprintf(fid, '%s\n', sprintf(varargin{:}));
https://riptutorial.com/it/home 166
fclose(fid); end end end end
e basta cambiare una riga di un codice in questo:
clc; % ... a code logger = DeepLogger('mymessages.log');
Il metodo sopra semplicemente aprirà un file, aggiungerà un messaggio alla fine del file e lo chiuderà. Al momento, per essere coerente con la mia interfaccia, ho bisogno di ricordare che il nome di un metodo è LogMessage() ma potrebbe essere ugualmente qualsiasi altra cosa. MATLAB può forzare lo sviluppatore ad attenersi allo stesso nome usando classi astratte. Supponiamo di definire un'interfaccia comune per qualsiasi registratore:
classdef MessageLogger methods(Abstract=true) LogMessage(obj, varargin); end end
Ora, se entrambi ScreenLogger e DeepLogger ereditano da questa classe, MATLAB genererà un errore se LogMessage() non è definito. Le classi astratte aiutano a costruire classi simili che possono utilizzare la stessa interfaccia.
Per il bene di questo exmaple, farò un cambiamento leggermente diverso. Suppongo che DeepLogger esegua entrambi i messaggi di registrazione su uno schermo e in un file contemporaneamente. Poiché ScreenLogger registra già i messaggi sullo schermo, erediterò DeepLogger dallo ScreenLoggger per evitare la ripetizione. ScreenLogger non cambia affatto a parte la prima riga:
classdef ScreenLogger < MessageLogger // the rest of previous code
Tuttavia, DeepLogger necessita di più modifiche nel metodo LogMessage :
classdef DeepLogger < MessageLogger & ScreenLogger properties(SetAccess=protected) FileName Path end methods function obj = DeepLogger(screenhandler, filename) [path,filen,ext] = fileparts(filename); obj.FileName = [filen ext]; pbj.Path = pathn; obj = obj@ScreenLogger(screenhandler); end function LogMessage(obj, varargin)
https://riptutorial.com/it/home 167
if ~isempty(varargin) varargin{1} = num2str(varargin{1}); LogMessage@ScreenLogger(obj, varargin{:}); fid = fopen(obj.fullfname, 'a+t'); fprintf(fid, '%s\n', sprintf(varargin{:})); fclose(fid); end end end end
Innanzitutto, inizializzo semplicemente le proprietà nel costruttore. In secondo luogo, poiché questa classe eredita da ScreenLogger devo inizializzare anche questo oggetto parrent. Questa linea è ancora più importante perché il costruttore ScreenLogger richiede un parametro per inizializzare il proprio oggetto. Questa linea:
obj = obj@ScreenLogger(screenhandler);
dice semplicemente "chiama il responsabile di ScreenLogger e inizializza con uno screen handler". Vale la pena notare qui che ho definito scrh come protetto. Pertanto, potrei ugualmente accedere a questa proprietà da DeepLogger . Se la proprietà è stata definita come privata. L'unico modo per inizializzarlo sarebbe utilizzare il consuctor.
Un altro cambiamento è nei methods sezione. Ancora una volta per evitare la ripetizione, chiamo LogMessage() da una classe genitore per registrare un messaggio su uno schermo. Se dovessi cambiare qualcosa per migliorare la registrazione dello schermo, ora devo farlo in un posto. Il codice di riposo è lo stesso in quanto fa parte di DeepLogger .
Poiché questa classe eredita anche da una classe astratta MessageLogger dovevo assicurarmi che anche LogMessage() all'interno di DeepLogger fosse definito. L'adesione a MessageLogger è un po 'complicata qui. Penso che la ridefinizione dei casi di LogMessage obbligatoria - la mia ipotesi.
In termini di codice in cui viene applicato un logger, grazie a un'interfaccia comune nelle classi, posso essere certo che questa riga dell'intero codice non creerebbe alcun problema. Gli stessi messaggi saranno sullo schermo come prima ma in aggiunta il codice scriverà tali messaggi su un file.
clc; % ... a code logger = DeepLogger(1, 'mylogfile.log'); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something'); % ... a code logger.LogMessage('something');
Spero che questi esempi spieghino l'uso delle classi, l'uso dell'ereditarietà e l'uso di classi astratte.
https://riptutorial.com/it/home 168
PS. La soluzione per il problema sopra riportato è una delle tante. Un'altra soluzione, meno complessa, sarebbe quella di rendere ScreenLoger un componente di un altro logger come FileLogger ecc. ScreenLogger sarebbe contenuto in una delle proprietà. Il suo LogMessage chiamerebbe semplicemente LogMessage di ScreenLogger e mostrerà il testo su uno schermo. Ho scelto un approccio più complesso per mostrare piuttosto come funzionano le classi in MATLAB. Il codice di esempio qui sotto:
classdef DeepLogger < MessageLogger properties(SetAccess=protected) FileName Path ScrLogger end methods function obj = DeepLogger(screenhandler, filename) [path,filen,ext] = fileparts(filename); obj.FileName = [filen ext]; obj.Path = pathn; obj.ScrLogger = ScreenLogger(screenhandler); end function LogMessage(obj, varargin) if ~isempty(varargin) varargin{1} = num2str(varargin{1}); obj.LogMessage(obj.ScrLogger, varargin{:}); % <-------- thechange here fid = fopen(obj.fullfname, 'a+t'); fprintf(fid, '%s\n', sprintf(varargin{:})); fclose(fid); end end end end
Costruttori
Un costruttore è un metodo speciale in una classe che viene chiamata quando viene creata un'istanza di un oggetto. È una normale funzione MATLAB che accetta i parametri di input ma deve anche seguire determinate regole .
I costruttori non sono obbligatori in quanto MATLAB ne crea uno predefinito. In pratica, tuttavia, questo è un posto dove definire uno stato di un oggetto. Ad esempio, le proprietà possono essere limitate specificando gli attributi . Quindi, un costruttore può initalizzare tali proprietà per impostazione predefinita o valori definiti dall'utente che, in effetti, possono essere inviati dai parametri di input di un costruttore.
Chiamando un costruttore di una classe semplice
Questa è una semplice classe Person .
classdef Person properties name surname address end
https://riptutorial.com/it/home 169
methods function obj = Person(name,surname,address) obj.name = name; obj.surname = surname; obj.address = address; end end end
Il nome di un costruttore è uguale al nome di una classe. Di conseguenza, i costruttori sono chiamati con il nome della sua classe. Una classe Person può essere creata come segue:
>> p = Person('John','Smith','London') p = Person with properties: name: 'John' surname: 'Smith' address: 'London'
Chiamare un costruttore di una classe figlio
Le classi possono essere ereditate dalle classi padre se condivide proprietà o metodi comuni. Quando una classe è ereditata da un'altra, è probabile che si debba chiamare un costruttore di una classe genitrice.
Un Member classe eredita da una classe Person perché Member utilizza le stesse proprietà della classe Person ma aggiunge anche il payment alla sua definizione.
classdef Member < Person properties payment end methods function obj = Member(name,surname,address,payment) obj = obj@Person(name,surname,address); obj.payment = payment; end end end
Analogamente alla classe Person , Member viene creato chiamando il suo costruttore:
>> m = Member('Adam','Woodcock','Manchester',20) m = Member with properties: payment: 20 name: 'Adam' surname: 'Woodcock' address: 'Manchester'
Un costruttore di Person richiede tre parametri di input. Member deve rispettare questo fatto e quindi
https://riptutorial.com/it/home 170
chiamare un costruttore della classe Person con tre parametri. È soddisfatto dalla linea:
obj = obj@Person(name,surname,address);
L'esempio sopra mostra il caso in cui una classe figlia ha bisogno di informazioni per la sua classe genitore. Ecco perché un costruttore di Member richiede quattro parametri: tre per la sua classe genitore e uno per se stesso.
Leggi Programmazione orientata agli oggetti online: https://riptutorial.com/it/matlab/topic/1028/programmazione-orientata-agli-oggetti
https://riptutorial.com/it/home 171
Capitolo 26: Risolutori di equazioni differenziali ordinarie (ODE)
Examples
Esempio per odeset
Innanzitutto inizializziamo il problema del valore iniziale che vogliamo risolvere.
odefun = @(t,y) cos(y).^2*sin(t); tspan = [0 16*pi]; y0=1;
Quindi usiamo la funzione ode45 senza alcuna opzione specificata per risolvere questo problema. Per confrontarlo in seguito, tracciamo la traiettoria.
[t,y] = ode45(odefun, tspan, y0); plot(t,y,'-o');
Ora stabiliamo un limite stretto e un limite assoluto di tolleranza per il nostro problema.
options = odeset('RelTol',1e-2,'AbsTol',1e-2); [t,y] = ode45(odefun, tspan, y0, options); plot(t,y,'-o');
Stabiliamo un limite assoluto di tolleranza stretto relativo e stretto.
options = odeset('RelTol',1e-7,'AbsTol',1e-2); [t,y] = ode45(odefun, tspan, y0, options); plot(t,y,'-o');
Stabiliamo un limite di tolleranza stretto relativo e stretto assoluto. Come negli esempi precedenti con limiti ristretti di tolleranza, la traiettoria è completamente diversa dalla prima trama senza opzioni specifiche.
options = odeset('RelTol',1e-2,'AbsTol',1e-7); [t,y] = ode45(odefun, tspan, y0, options); plot(t,y,'-o');
Stabiliamo un limite di tolleranza stretto relativo e stretto assoluto. Confrontando il risultato con l'altro grafico si evidenzieranno gli errori effettuati calcolando con limiti di tolleranza stretti.
options = odeset('RelTol',1e-7,'AbsTol',1e-7); [t,y] = ode45(odefun, tspan, y0, options); plot(t,y,'-o');
https://riptutorial.com/it/home 172
Quanto segue dovrebbe dimostrare il compromesso tra precisione e tempo di esecuzione.
tic; options = odeset('RelTol',1e-7,'AbsTol',1e-7); [t,y] = ode45(odefun, tspan, y0, options); time1 = toc; plot(t,y,'-o');
Per confronto si stringe il limite di tolleranza per l'errore assoluto e relativo. Ora possiamo vedere che senza un grande guadagno di precisione ci vorrà molto più tempo per risolvere il nostro problema del valore iniziale.
tic; options = odeset('RelTol',1e-13,'AbsTol',1e-13); [t,y] = ode45(odefun, tspan, y0, options); time2 = toc; plot(t,y,'-o');
Leggi Risolutori di equazioni differenziali ordinarie (ODE) online: https://riptutorial.com/it/matlab/topic/6079/risolutori-di-equazioni-differenziali-ordinarie--ode-
https://riptutorial.com/it/home 173
Capitolo 27: Scomposizioni della matrice
Sintassi
R = chol (A);1. [L, U] = lu (A);2. R = qr (A);3. T = schur (A);4. [U, S, V] = svd (A);5.
Examples
Scomposizione di Cholesky
La scomposizione di Cholesky è un metodo per decomporre una matrice ermetica, positivamente definita in una matrice triangolare superiore e la sua trasposizione. Può essere utilizzato per risolvere sistemi di equazioni lineari ed è circa il doppio della decomposizione LU.
A = [4 12 -16 12 37 -43 -16 -43 98]; R = chol(A);
Questo restituisce la matrice triangolare superiore. Quello inferiore è ottenuto per trasposizione.
L = R';
Finalmente possiamo controllare se la decomposizione è stata corretta.
b = (A == L*R);
Decomposizione QR
Questo metodo decompone una matrice in una matrice triangolare superiore e una matrice ortogonale.
A = [4 12 -16 12 37 -43 -16 -43 98]; R = qr(A);
Ciò restituirà la matrice triangolare superiore mentre il seguente restituirà entrambe le matrici.
[Q,R] = qr(A);
https://riptutorial.com/it/home 174
Il grafico seguente mostra il tempo di esecuzione di qr dipendente dalla radice quadrata degli elementi della matrice.
Decomposizione LU
In questo modo una matrice sarà scomposta in una matrice triangolare superiore e inferiore. Spesso sarà usato per aumentare le prestazioni e la stabilità (se è fatta con permutazione) dell'eliminazione di Gauß.
Tuttavia, molto spesso questo metodo non funziona o funziona male in quanto non è stabile. Per esempio
A = [8 1 6 3 5 7 4 9 2]; [L,U] = lu(A);
È sufficiente aggiungere una matrice di permutazione tale che PA = LU:
[L,U,P]=lu(A);
Nel seguito, ora tracciamo il tempo di esecuzione di "lu" dipendente dalla radice quadrata degli elementi della matrice.
https://riptutorial.com/it/home 175
Scomposizione di Schur
Se A è una matrice complessa e quadratica esiste una Q unitaria tale che Q * AQ = T = D + N con D essendo la matrice diagonale costituita dagli autovalori e N essendo strettamente tridiagonale superiore.
A = [3 6 1 23 13 1 0 3 4]; T = schur(A);
Visualizziamo anche il tempo di esecuzione di schur base alla radice quadrata degli elementi di matrice:
https://riptutorial.com/it/home 176
Scomposizione di un valore singolo
Dato un m volte n matrice A con n maggiore di m. La decomposizione del valore singolare
[U,S,V] = svd(A);
calcola le matrici U, S, V.
La matrice U è costituita dai singoli autovettori di sinistra che sono gli autovettori di A*A.' mentre V è costituito dagli autovalori singolari giusti che sono gli autovettori di A.'*A La matrice S ha le radici quadrate degli autovalori di A*A.' e A.'*A sulla sua diagonale.
Se m è più grande di n si può usare
[U,S,V] = svd(A,'econ');
per eseguire la decomposizione del valore singolare di dimensioni economiche.
Leggi Scomposizioni della matrice online: https://riptutorial.com/it/matlab/topic/6163/scomposizioni-della-matrice
https://riptutorial.com/it/home 177
Capitolo 28: Trasformate di Fourier e Trasformate di Fourier inverse
Sintassi
Y = fft (X)% calcola la FFT di Vector o Matrix X utilizzando una lunghezza di trasformazione predefinita di 256 (da confermare per la versione)
1.
Y = fft (X, n)% calcola la FFT di X usando n come Transform Length, n deve essere un numero basato su 2-power. Se la lunghezza di X è minore di n, allora Matlab calcola automaticamente X con zeri tali che la lunghezza (X) = n
2.
Y = fft (X, n, dim)% calcola la FFT di X usando n come Transform Length lungo dim dimensionale (può essere 1 o 2 per orizzontale o verticale rispettivamente)
3.
Y = fft2 (X)% Calcola la FFT 2D di X4.
Y = fftn (X, dim)% Calcola la FFT dim-dimensionale di X, rispetto al vettore di dimensioni dim.
5.
y = ifft (X)% calcola l'inverso di FFT di X (che è una matrice / vettore di numeri) utilizzando la lunghezza di trasformazione 256 predefinita
6.
y = ifft (X, n)% calcola l'IFFT di X usando n come Transform Length7.
y = ifft (X, n, dim)% calcola l'IFFT di X usando n come Transform Length over dim dim (può essere 1 o 2 per orizzontale o verticale rispettivamente)
8.
y = ifft (X, n, dim, 'symmetric')% L'opzione Symmetric fa sì che ifft tratti X come coniugato simmetrico lungo la dimensione attiva. Questa opzione è utile quando X non è esattamente simmetrico coniugato, semplicemente a causa di un errore di arrotondamento.
9.
y = ifft2 (X)% Calcola i metri 2D inversi di X10.
y = ifftn (X, dim)% Calcola il fft dim dimensionale inverso di X.11.
Parametri
Parametro Descrizione
Xquesto è il segnale in ingresso nel dominio del tempo, dovrebbe essere un vettore di numeri.
nquesto è il parametro NFFT noto come Transform Length, pensalo come una risoluzione del tuo risultato FFT, DEVE essere un numero che è una potenza di 2 (cioè 64,128,256 ... 2 ^ N)
https://riptutorial.com/it/home 178
Parametro Descrizione
offuscare
questa è la dimensione su cui vuoi calcolare FFT, usa 1 se vuoi calcolare la tua FFT in direzione orizzontale e 2 se vuoi calcolare la tua FFT in direzione verticale - Nota questo parametro di solito è lasciato in bianco, poiché la funzione è in grado di rilevare la direzione del tuo vettore.
Osservazioni
Matlab FFT è un processo molto parallelo in grado di gestire grandi quantità di dati. Può anche utilizzare la GPU con un enorme vantaggio.
ifft(fft(X)) = X
L'affermazione sopra è vera se gli errori di arrotondamento sono omessi.
Examples
Implementa una semplice trasformazione di Fourier in Matlab
Fourier Transform è probabilmente la prima lezione in Digital Signal Processing, la sua applicazione è ovunque ed è uno strumento potente quando si tratta di analizzare dati (in tutti i settori) o segnali. Matlab ha un set di potenti toolbox per la trasformata di Fourier. In questo esempio, useremo la trasformata di Fourier per analizzare un segnale sinusoidale di base e generare quello che a volte è noto come un periodogramma usando FFT:
%Signal Generation A1=10; % Amplitude 1 A2=10; % Amplitude 2 w1=2*pi*0.2; % Angular frequency 1 w2=2*pi*0.225; % Angular frequency 2 Ts=1; % Sampling time N=64; % Number of process samples to be generated K=5; % Number of independent process realizations sgm=1; % Standard deviation of the noise n=repmat([0:N-1].',1,K); % Generate resolution phi1=repmat(rand(1,K)*2*pi,N,1); % Random phase matrix 1 phi2=repmat(rand(1,K)*2*pi,N,1); % Random phase matrix 2 x=A1*sin(w1*n*Ts+phi1)+A2*sin(w2*n*Ts+phi2)+sgm*randn(N,K); % Resulting Signal NFFT=256; % FFT length F=fft(x,NFFT); % Fast Fourier Transform Result Z=1/N*abs(F).^2; % Convert FFT result into a Periodogram
https://riptutorial.com/it/home 179
Nota che la Trasformata di Fourier Discreta è implementata da Fast Fourier Transform (fft) in Matlab, entrambi produrranno lo stesso risultato, ma FFT è un'implementazione veloce di DFT.
figure w=linspace(0,2,NFFT); plot(w,10*log10(Z)),grid; xlabel('w [\pi rad/s]') ylabel('Z(f) [dB]') title('Frequency Range: [ 0 , \omega_s ]')
Trasformate di Fourier inverse
Uno dei principali vantaggi di Fourier Transform è la sua capacità di tornare al dominio del tempo senza perdere informazioni. Consideriamo lo stesso segnale che abbiamo usato nell'esempio precedente:
A1=10; % Amplitude 1 A2=10; % Amplitude 2 w1=2*pi*0.2; % Angular frequency 1 w2=2*pi*0.225; % Angular frequency 2 Ts=1; % Sampling time N=64; % Number of process samples to be generated K=1; % Number of independent process realizations sgm=1; % Standard deviation of the noise n=repmat([0:N-1].',1,K); % Generate resolution phi1=repmat(rand(1,K)*2*pi,N,1); % Random phase matrix 1 phi2=repmat(rand(1,K)*2*pi,N,1); % Random phase matrix 2 x=A1*sin(w1*n*Ts+phi1)+A2*sin(w2*n*Ts+phi2)+sgm*randn(N,K); % Resulting Signal NFFT=256; % FFT length
https://riptutorial.com/it/home 180
F=fft(x,NFFT); % FFT result of time domain signal
Se apriamo F in Matlab, scopriremo che è una matrice di numeri complessi, una parte reale e una parte immaginaria. Per definizione, al fine di recuperare il segnale del dominio del tempo originale, abbiamo bisogno sia del Real (che rappresenta la variazione di Magnitudo) sia dell'Imaginario (che rappresenta la variazione di Fase), quindi per tornare al dominio del tempo, si può semplicemente voler:
TD = ifft(F,NFFT); %Returns the Inverse of F in Time Domain
Nota che TD restituito sarebbe lungo 256 perché impostiamo NFFT su 256, tuttavia, la lunghezza di x è solo 64, quindi Matlab eseguirà il pad degli zeri fino alla fine della trasformazione TD. Ad esempio, se NFFT era 1024 e la lunghezza era 64, TD restituito sarà 64 + 960 zeri. Si noti inoltre che a causa dell'arrotondamento in virgola mobile, è possibile ottenere qualcosa come 3.1 * 10e-20 ma per scopi generali: per ogni X, ifft (fft (X)) equivale a X fino all'errore roundoff.
Diciamo per un momento che dopo la trasformazione, abbiamo fatto qualcosa e siamo rimasti solo con la parte REALE della FFT:
R = real(F); %Give the Real Part of the FFT TDR = ifft(R,NFFT); %Give the Time Domain of the Real Part of the FFT
Ciò significa che stiamo perdendo la parte immaginaria della nostra FFT e, pertanto, stiamo perdendo informazioni in questo processo inverso. Per preservare l'originale senza perdere informazioni, dovresti sempre mantenere la parte immaginaria della FFT usando imag e applicare le tue funzioni a entrambi o alla parte reale.
figure subplot(3,1,1) plot(x);xlabel('time samples');ylabel('magnitude');title('Original Time Domain Signal') subplot(3,1,2) plot(TD(1:64));xlabel('time samples');ylabel('magnitude');title('Inverse Fourier Transformed - Time Domain Signal') subplot(3,1,3) plot(TDR(1:64));xlabel('time samples');ylabel('magnitude');title('Real part of IFFT transformed Time Domain Signal')
https://riptutorial.com/it/home 181
Immagini e FT multidimensionali
Nell'imaging medico, nella spettroscopia, nell'elaborazione delle immagini, nella crittografia e in altre aree della scienza e dell'ingegneria, è spesso il caso che si desideri calcolare trasformazioni multidimensionali di Fourier delle immagini. Questo è abbastanza semplice in Matlab: le immagini (multidimensionali) sono solo matrici n-dimensionali, dopotutto, e le trasformate di Fourier sono operatori lineari: uno solo iterativamente trasforma Fourier lungo altre dimensioni. Matlab fornisce fft2 e ifft2 per farlo in 2-d o fftn in n-dimensioni.
Una potenziale trappola è che la trasformata di Fourier delle immagini viene solitamente mostrata "ordinata centrica", cioè con l'origine dello spazio-k nel mezzo dell'immagine. Matlab fornisce il comando fftshift per scambiare fftshift la posizione dei componenti DC della trasformata di Fourier. Questa notazione di ordinamento rende sostanzialmente più semplice l'esecuzione di tecniche di elaborazione di immagini comuni, una delle quali è illustrata di seguito.
Riempimento a zero
Un modo "veloce e sporco" di interpolare una piccola immagine ad una dimensione più grande è trasformarlo in Fourier, riempire la trasformata di Fourier con zeri e poi prendere la trasformazione inversa. Questo interpola in modo efficace tra ciascun pixel con una funzione di base a forma di sincro, ed è comunemente usato per i dati di imaging medico in bassa risoluzione su scala. Iniziamo caricando un esempio di immagine incorporata
https://riptutorial.com/it/home 182
%Load example image I=imread('coins.png'); %Load example data -- coins.png is builtin to Matlab I=double(I); %Convert to double precision -- imread returns integers imageSize = size(I); % I is a 246 x 300 2D image %Display it imagesc(I); colormap gray; axis equal; %imagesc displays images scaled to maximum intensity
Ora possiamo ottenere la trasformata di Fourier di I. Per illustrare cosa fa il fftshift , confrontiamo i due metodi:
% Fourier transform %Obtain the centric- and non-centric ordered Fourier transform of I k=fftshift(fft2(fftshift(I))); kwrong=fft2(I); %Just for the sake of comparison, show the magnitude of both transforms: figure; subplot(2,1,1); imagesc(abs(k),[0 1e4]); colormap gray; axis equal; subplot(2,1,2); imagesc(abs(kwrong),[0 1e4]); colormap gray; axis equal; %(The second argument to imagesc sets the colour axis to make the difference clear).
https://riptutorial.com/it/home 183
Ora abbiamo ottenuto il FT 2D di un'immagine di esempio. Per riempirlo a zero, vogliamo prendere ogni k-spazio, riempire i bordi con zeri e quindi prendere la trasformazione posteriore:
%Zero fill kzf = zeros(imageSize .* 2); %Generate a 492x600 empty array to put the result in kzf(end/4:3*end/4-1,end/4:3*end/4-1) = k; %Put k in the middle kzfwrong = zeros(imageSize .* 2); %Generate a 492x600 empty array to put the result in kzfwrong(end/4:3*end/4-1,end/4:3*end/4-1) = kwrong; %Put k in the middle %Show the differences again %Just for the sake of comparison, show the magnitude of both transforms: figure; subplot(2,1,1); imagesc(abs(kzf),[0 1e4]); colormap gray; axis equal; subplot(2,1,2); imagesc(abs(kzfwrong),[0 1e4]); colormap gray; axis equal; %(The second argument to imagesc sets the colour axis to make the difference clear).
A questo punto, il risultato è abbastanza insignificante:
https://riptutorial.com/it/home 184
Una volta che prendiamo le back-transforms, possiamo vedere che (correttamente!) I dati a riempimento zero forniscono un metodo ragionevole per l'interpolazione:
% Take the back transform and view Izf = fftshift(ifft2(ifftshift(kzf))); Izfwrong = ifft2(kzfwrong); figure; subplot(1,3,1); imagesc(abs(Izf)); colormap gray; axis equal; title('Zero-filled image'); subplot(1,3,2); imagesc(abs(Izfwrong)); colormap gray; axis equal; title('Incorrectly zero-filled image'); subplot(1,3,3); imagesc(I); colormap gray; axis equal; title('Original image'); set(gcf,'color','w');
https://riptutorial.com/it/home 185
Si noti che la dimensione dell'immagine riempita a zero è il doppio dell'originale. Si può riempire a zero di più di un fattore due in ciascuna dimensione, anche se ovviamente farlo non aumenta arbitrariamente la dimensione di un'immagine.
Suggerimenti, consigli, 3D e oltre
L'esempio sopra vale per le immagini 3D (come spesso sono generate dalle tecniche di imaging medico o dalla microscopia confocale, per esempio), ma richiede che fft2 sia sostituito da fftn(I, 3) , per esempio. A causa della natura alquanto scomoda della scrittura di fftshift(fft(fftshift(... più volte, è abbastanza comune definire funzioni come fft2c localmente per fornire una sintassi più semplice a livello locale, come ad esempio:
function y = fft2c(x) y = fftshift(fft2(fftshift(x)));
https://riptutorial.com/it/home 186
Nota che la FFT è veloce, ma le trasformazioni di Fourier multidimensionali di grandi dimensioni richiederanno ancora del tempo su un computer moderno. È inoltre intrinsecamente complesso: la grandezza dello spazio-k è stata mostrata sopra, ma la fase è assolutamente vitale; le traduzioni nel dominio dell'immagine sono equivalenti a una rampa di fase nel dominio di Fourier. Ci sono molte operazioni molto più complesse che si potrebbero desiderare di fare nel dominio di Fourier, come filtrare frequenze spaziali alte o basse (moltiplicandolo con un filtro), o mascherare i punti discreti corrispondenti al rumore. Esiste corrispondentemente una grande quantità di codice generato dalla comunità per la gestione delle operazioni di Fourier comuni disponibili sul sito di repository della comunità principale di Matlab, il File Exchange .
Leggi Trasformate di Fourier e Trasformate di Fourier inverse online: https://riptutorial.com/it/matlab/topic/2181/trasformate-di-fourier-e-trasformate-di-fourier-inverse
https://riptutorial.com/it/home 187
Capitolo 29: Trucchi utili
Examples
Funzioni utili che operano su celle e array
Questo semplice esempio fornisce una spiegazione su alcune funzioni che ho trovato estremamente utili da quando ho iniziato ad usare MATLAB: cellfun , arrayfun . L'idea è di prendere una variabile di classe array o cellula, scorrere tutti i suoi elementi e applicare una funzione dedicata su ciascun elemento. Una funzione applicata può essere anonima, che di solito è un caso, o qualsiasi funzione regolare definita in un file * .m.
Iniziamo con un semplice problema e diciamo che dobbiamo trovare un elenco di file * .mat dati la cartella. Per questo esempio, per prima cosa creiamo alcuni file * .mat in una cartella corrente:
for n=1:10; save(sprintf('mymatfile%d.mat',n)); end
Dopo aver eseguito il codice, dovrebbero esserci 10 nuovi file con estensione * .mat. Se eseguiamo un comando per elencare tutti i file * .mat, ad esempio:
mydir = dir('*.mat');
dovremmo ottenere una serie di elementi di una struttura dir; MATLAB dovrebbe dare un risultato simile a questo:
10x1 struct array with fields: name date bytes isdir datenum
Come puoi vedere, ogni elemento di questo array è una struttura con un paio di campi. Tutte le informazioni sono davvero importanti per ogni file, ma nel 99% sono piuttosto interessato ai nomi di file e nient'altro. Per estrarre informazioni da un array di strutture, ho usato per creare una funzione locale che implicherebbe la creazione di variabili temporali di una dimensione corretta, per cicli, estrarre un nome da ciascun elemento e salvarlo nella variabile creata. Un modo molto più semplice per ottenere esattamente lo stesso risultato è usare una delle funzioni di cui sopra:
mydirlist = arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false) mydirlist = 'mymatfile1.mat' 'mymatfile10.mat' 'mymatfile2.mat' 'mymatfile3.mat' 'mymatfile4.mat' 'mymatfile5.mat' 'mymatfile6.mat'
https://riptutorial.com/it/home 188
'mymatfile7.mat' 'mymatfile8.mat' 'mymatfile9.mat'
Come funziona questa funzione? Di solito prende due parametri: una funzione gestisce come primo parametro e un array. Una funzione quindi opererà su ciascun elemento di un dato array. Il terzo e il quarto parametro sono facoltativi ma importanti. Se sappiamo che un output non sarà regolare, deve essere salvato nella cella. Questo deve essere indicato impostando false su UniformOutput . Di default questa funzione tenta di restituire un output regolare come un vettore di numeri. Ad esempio, estrapiamo informazioni sulla quantità di spazio su disco utilizzato da ciascun file in byte:
mydirbytes = arrayfun(@(x) x.bytes, dir('*.mat')) mydirbytes = 34560 34560 34560 34560 34560 34560 34560 34560 34560 34560
o kilobyte:
mydirbytes = arrayfun(@(x) x.bytes/1024, dir('*.mat')) mydirbytes = 33.7500 33.7500 33.7500 33.7500 33.7500 33.7500 33.7500 33.7500 33.7500 33.7500
Questa volta l'output è un normale vettore di doppio. UniformOutput stato impostato su true per impostazione predefinita.
cellfun è una funzione simile. La differenza tra questa funzione e arrayfun è che cellfun opera sulle variabili di classe delle celle. Se desideriamo estrarre solo i nomi dati da un elenco di nomi di file in una cella "mydirlist", avremmo solo bisogno di eseguire questa funzione come segue:
mydirnames = cellfun(@(x) x(1:end-4), mydirlist, 'UniformOutput', false) mydirnames = 'mymatfile1' 'mymatfile10' 'mymatfile2' 'mymatfile3' 'mymatfile4'
https://riptutorial.com/it/home 189
'mymatfile5' 'mymatfile6' 'mymatfile7' 'mymatfile8' 'mymatfile9'
Di nuovo, poiché un output non è un normale vettore di numeri, un output deve essere salvato in una variabile di cella.
Nell'esempio seguente, combino due funzioni in una e restituisco solo un elenco di nomi di file senza un'estensione:
cellfun(@(x) x(1:end-4), arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false), 'UniformOutput', false) ans = 'mymatfile1' 'mymatfile10' 'mymatfile2' 'mymatfile3' 'mymatfile4' 'mymatfile5' 'mymatfile6' 'mymatfile7' 'mymatfile8' 'mymatfile9'
È pazzesco ma molto possibile perché arrayfun restituisce una cella che è l'input previsto di cellfun ; una nota a UniformOutput è che possiamo forzare una di queste funzioni a restituire risultati in una variabile di cella impostando UniformOutput su false, esplicitamente. Possiamo sempre ottenere risultati in una cella. Potremmo non essere in grado di ottenere risultati in un vettore normale.
C'è un'altra funzione simile che opera sui campi di una struttura: structfun . Non l'ho trovato particolarmente utile come gli altri due, ma in alcune situazioni potrebbe brillare. Se ad esempio si desidera sapere quali campi sono numerici o non numerici, il seguente codice può dare la risposta:
structfun(@(x) ischar(x), mydir(1))
Il primo e il secondo campo di una struttura dir sono di tipo char. Pertanto, l'output è:
1 1 0 0 0
Inoltre, l'output è un vettore logico di true / false . Di conseguenza, è regolare e può essere salvato in un vettore; non c'è bisogno di usare una classe di cellule.
Preferenze di piegatura del codice
https://riptutorial.com/it/home 190
È possibile modificare la preferenza di piegatura del codice in base alle proprie esigenze. In questo modo è possibile impostare l'abilitazione / disabilitazione del codice per specifici costrutti (es: if block , for loop , Sections ...).
Per modificare le preferenze di piegatura, vai a Preferenze -> Piegatura codice:
Quindi puoi scegliere quale parte del codice può essere piegata.
Alcune informazioni:
Tieni presente che puoi anche espandere o comprimere tutto il codice in un file posizionando il cursore ovunque all'interno del file, fare clic con il pulsante destro del mouse e quindi selezionare Piegatura codice> Espandi tutto o Piegatura codice> Piega tutto dal menu di scelta rapida.
•
Si noti che il folding è persistente, nel senso che parte del codice che è stato espanso / compresso manterrà il proprio stato dopo Matlab o il file m è stato chiuso e riaperto.
•
https://riptutorial.com/it/home 191
Esempio: per abilitare il piegamento per le sezioni:
Un'opzione interessante è abilitare a piegare le sezioni. Le sezioni sono delimitate da due segni di percentuale ( %% ).
Esempio: per abilitarlo seleziona la casella "Sezioni":
Quindi, invece di vedere un codice sorgente lungo simile a:
https://riptutorial.com/it/home 192
Potrai piegare le sezioni per avere una panoramica generale del tuo codice:
Estrai dati figure
In alcune occasioni, ho avuto una figura interessante che ho salvato, ma ho perso un accesso ai suoi dati. Questo esempio mostra un trucco su come ottenere informazioni da una figura.
Le funzioni chiave sono findobj e get . findobj restituisce un gestore a un oggetto dati attributi o proprietà dell'oggetto, come Type o Color , ecc. Una volta che un oggetto linea è stato trovato, get può restituire qualsiasi valore posseduto dalle proprietà. Si scopre che gli oggetti Line contengono tutti i dati nelle seguenti proprietà: XData , YData e ZData ; l'ultimo è di solito 0 a meno che una figura contenga un grafico 3D.
Il codice seguente crea una figura di esempio che mostra due linee una funzione sin e una soglia e una legenda
t = (0:1/10:1-1/10)'; y = sin(2*pi*t); plot(t,y); hold on; plot([0 0.9],[0 0], 'k-'); hold off; legend({'sin' 'threshold'});
Il primo utilizzo di findobj restituisce due gestori su entrambe le righe:
findobj(gcf, 'Type', 'Line') ans = 2x1 Line array: Line (threshold) Line (sin)
Per restringere il risultato, findobj può anche utilizzare la combinazione di operatori logici -and , -or nomi di proprietà. Ad esempio, posso trovare un oggetto linea il cui DiplayName è sin e leggere i suoi XData e YData .
https://riptutorial.com/it/home 193
lineh = findobj(gcf, 'Type', 'Line', '-and', 'DisplayName', 'sin'); xdata = get(lineh, 'XData'); ydata = get(lineh, 'YData');
e controllare se i dati sono uguali.
isequal(t(:),xdata(:)) ans = 1 isequal(y(:),ydata(:)) ans = 1
Allo stesso modo, posso restringere i miei risultati escludendo la linea nera (soglia):
lineh = findobj(gcf, 'Type', 'Line', '-not', 'Color', 'k'); xdata = get(lineh, 'XData'); ydata = get(lineh, 'YData');
e l'ultimo controllo conferma che i dati estratti da questa figura sono gli stessi:
isequal(t(:),xdata(:)) ans = 1 isequal(y(:),ydata(:)) ans = 1
Programmazione funzionale usando le funzioni anonime
Le funzioni anonime possono essere utilizzate per la programmazione funzionale. Il problema principale da risolvere è che non esiste un modo nativo per l'ancoraggio di una ricorsione, ma questo può ancora essere implementato in una singola riga:
if_ = @(bool, tf) tf{2-bool}();
Questa funzione accetta un valore booleano e un array di celle di due funzioni. La prima di queste funzioni viene valutata se il valore booleano viene valutato come true e il secondo se il valore booleano viene valutato come falso. Ora possiamo facilmente scrivere la funzione fattoriale:
fac = @(n,f) if_(n>1, {@()n*f(n-1,f), @()1});
Il problema qui è che non possiamo invocare direttamente una chiamata ricorsiva, poiché la funzione non è ancora assegnata a una variabile quando viene valutata la parte destra. Possiamo tuttavia completare questo passaggio scrivendo
factorial_ = @(n)fac(n,fac);
Ora @(n)fac(n,fac) eva ricorsivamente la funzione fattoriale. Un altro modo per farlo nella
https://riptutorial.com/it/home 194
programmazione funzionale usando un combinatore y, che può anche essere facilmente implementato:
y_ = @(f)@(n)f(n,f);
Con questo strumento, la funzione fattoriale è ancora più breve:
factorial_ = y_(fac);
O direttamente:
factorial_ = y_(@(n,f) if_(n>1, {@()n*f(n-1,f), @()1}));
Salva più figure nello stesso file .fig
Inserendo più handle di figure in una matrice grafica, è possibile salvare più figure nello stesso file .fig
h(1) = figure; scatter(rand(1,100),rand(1,100)); h(2) = figure; scatter(rand(1,100),rand(1,100)); h(3) = figure; scatter(rand(1,100),rand(1,100)); savefig(h,'ThreeRandomScatterplots.fig'); close(h);
Questo crea 3 scatterplot di dati casuali, ogni parte dell'array grafico h. Quindi l'array grafico può essere salvato usando savefig come con una figura normale, ma con l'handle dell'array grafico come argomento aggiuntivo.
Una nota interessante è che le figure tenderanno a rimanere disposte nello stesso modo in cui sono state salvate quando le apri.
Blocchi di commento
Se vuoi commentare parte del tuo codice, i blocchi di commento possono essere utili. Il blocco dei commenti inizia con %{ in una nuova riga e termina con %} in un'altra nuova riga:
a = 10; b = 3; %{ c = a*b; d = a-b; %}
Questo ti permette di piegare le sezioni che hai commentato per rendere il codice più pulito e
https://riptutorial.com/it/home 195
compatto.
Questi blocchi sono anche utili per attivare / disattivare parti del tuo codice. Tutto quello che devi fare per decommentare il blocco è aggiungere un'altra % prima di strats:
a = 10; b = 3; %%{ <-- another % over here c = a*b; d = a-b; %}
A volte vuoi commentare una sezione del codice, ma senza intaccare il suo rientro:
for k = 1:a b = b*k; c = c-b; d = d*c; disp(b) end
Di solito, quando contrassegni un blocco di codice e premi Ctrl + r per commentarlo (aggiungendo il % automaticamente a tutte le linee, poi quando premi Ctrl + i per il rientro automatico, il blocco di codice si sposta dalla sua gerarchia corretta posto e spostato troppo a destra:
for k = 1:a b = b*k; % c = c-b; % d = d*c; disp(b) end
Un modo per risolverlo è usare i blocchi di commento, così la parte interna del blocco rimane correttamente rientrata:
for k = 1:a b = b*k; %{ c = c-b; d = d*c; %} disp(b) end
Leggi Trucchi utili online: https://riptutorial.com/it/matlab/topic/4179/trucchi-utili
https://riptutorial.com/it/home 196
Capitolo 30: Usando le porte seriali
introduzione
Le porte seriali sono un'interfaccia comune per la comunicazione con sensori esterni o sistemi embedded come Arduinos. Le moderne comunicazioni seriali sono spesso implementate tramite connessioni USB usando adattatori USB-seriali. MATLAB fornisce funzioni integrate per le comunicazioni seriali, inclusi i protocolli RS-232 e RS-485. Queste funzioni possono essere utilizzate per porte seriali hardware o connessioni USB-seriale "virtuali". Gli esempi qui illustrano le comunicazioni seriali in MATLAB.
Parametri
Parametro porta seriale
cosa fa
BaudRateImposta il baud rate. Il più comune oggi è 57600, ma sono spesso visti anche 4800, 9600 e 115200
InputBufferSize
Il numero di byte conservati in memoria. Matlab ha un FIFO, il che significa che i nuovi byte saranno scartati. Il valore predefinito è 512 byte, ma può essere facilmente impostato su 20 MB senza problemi. Ci sono solo alcuni casi limite in cui l'utente vorrebbe che fosse piccolo
BytesAvailable Il numero di byte in attesa di essere letti
ValuesSent Il numero di byte inviati da quando la porta è stata aperta
ValuesReceived Il numero di byte letti da quando la porta è stata aperta
BytesAvailableFcnSpecificare la funzione di callback da eseguire quando un numero specificato di byte è disponibile nel buffer di input o viene letto un terminatore
BytesAvailableFcnCountSpecificare il numero di byte che devono essere disponibili nel buffer di input per generare un evento bytes-available
BytesAvailableFcnModeSpecificare se l'evento bytes-available viene generato dopo che un numero specificato di byte è disponibile nel buffer di input o dopo la lettura di un terminatore
Examples
https://riptutorial.com/it/home 197
Creazione di una porta seriale su Mac / Linux / Windows
% Define serial port with a baud rate of 115200 rate = 115200; if ispc s = serial('COM1', 'BaudRate',rate); elseif ismac % Note that on OSX the serial device is uniquely enumerated. You will % have to look at /dev/tty.* to discover the exact signature of your % serial device s = serial('/dev/tty.usbserial-A104VFT7', 'BaudRate',rate); elseif isunix s = serial('/dev/ttyusb0', 'BaudRate',rate); end % Set the input buffer size to 1,000,000 bytes (default: 512 bytes). s.InputBufferSize = 1000000; % Open serial port fopen(s);
Lettura dalla porta seriale
Supponendo che si è creato l'oggetto porta seriale s come in questo esempio, allora
% Read one byte data = fread(s, 1); % Read all the bytes, version 1 data = fread(s); % Read all the bytes, version 2 data = fread(s, s.BytesAvailable); % Close the serial port fclose(s);
Chiusura di una porta seriale anche se persa, cancellata o sovrascritta
Supponendo che si è creato l'oggetto porta seriale s come in questo esempio, allora per chiuderlo
fclose(s)
Tuttavia, a volte è possibile perdere accidentalmente la porta (ad es. Cancellare, sovrascrivere, cambiare ambito, ecc.) E fclose(s) non funzionerà più. La soluzione è facile
fclose(instrfindall)
Maggiori informazioni su instrfindall() .
Scrivere sulla porta seriale
https://riptutorial.com/it/home 198
Supponendo che si è creato l'oggetto porta seriale s come in questo esempio, allora
% Write one byte fwrite(s, 255); % Write one 16-bit signed integer fwrite(s, 32767, 'int16'); % Write an array of unsigned 8-bit integers fwrite(s,[48 49 50],'uchar'); % Close the serial port fclose(s);
Scegli la tua modalità di comunicazione
Matlab supporta la comunicazione sincrona e asincrona con una porta seriale. È importante scegliere la giusta modalità di comunicazione. La scelta dipenderà da:
come si comportano gli strumenti con cui stai comunicando.•quali altre funzioni il tuo programma principale (o GUI) dovrà fare a parte la gestione della porta seriale.
•
Definirò 3 diversi casi da illustrare, dai più semplici ai più esigenti. Per i 3 esempi, lo strumento a cui mi sto collegando è un circuito stampato con un inclinometro, che può funzionare nelle 3 modalità che descriverò di seguito.
Modalità 1: sincrono (master / slave)
Questa modalità è la più semplice. Corrisponde al caso in cui il PC è il Master e lo strumento è lo slave . Lo strumento non invia nulla alla porta seriale, ma risponde solo dopo aver ricevuto una domanda / comando dal Master (il PC, il programma). Per esempio:
Il PC invia un comando: "Datemi una misura ora"•Lo strumento riceve il comando, prende la misura e restituisce il valore di misurazione alla linea seriale: "Il valore dell'inclinometro è XXX".
•
O
Il PC invia un comando: "Cambia dalla modalità X alla modalità Y"•Lo strumento riceve il comando, lo esegue, quindi invia un messaggio di conferma alla linea seriale: " Comando eseguito " (o " Comando NON eseguito "). Questo è comunemente chiamato risposta ACK / NACK (per "Acknowledge (d)" / "NOT Acknowledged").
•
Riepilogo: in questa modalità, lo strumento (lo Slave ) invia i dati alla linea seriale immediatamente dopo essere stato richiesto dal PC (il Master )
https://riptutorial.com/it/home 199
Modalità 2: asincrona
Ora supponiamo di aver avviato il mio strumento, ma è più di un semplice sensore stupido. Controlla costantemente la propria inclinazione e finché è verticale (entro una tolleranza, diciamo +/- 15 gradi), rimane in silenzio. Se il dispositivo è inclinato di oltre 15 gradi e si avvicina all'orizzontale, invia un messaggio di allarme alla linea seriale, immediatamente seguito da una lettura dell'inclinazione. Finché l'inclinazione è sopra la soglia, continua a inviare una lettura di inclinazione ogni 5 secondi.
Se il tuo programma principale (o GUI) è costantemente "in attesa" del messaggio che arriva sulla linea seriale, può farlo bene ... ma nel frattempo non può fare altro. Se il programma principale è una GUI, è altamente frustrante avere una GUI apparentemente "bloccata" perché non accetterà alcun input da parte dell'utente. Essenzialmente, è diventato lo schiavo e lo strumento è il maestro . A meno che non abbiate un modo elegante per controllare la vostra GUI dallo strumento, questo è qualcosa da evitare. Fortunatamente, la modalità di comunicazione asincrona ti consente di:
definire una funzione separata che indica al programma cosa fare quando viene ricevuto un messaggio
•
mantenere questa funzione in un angolo, verrà solo richiamata ed eseguita quando un messaggio arriva sulla linea seriale. Il resto del tempo la GUI può eseguire qualsiasi altro codice che deve essere eseguito.
•
Riepilogo: in questa modalità, lo strumento può inviare messaggi alla linea seriale in qualsiasi momento (ma non necessariamente per tutto il tempo). Il PC non attende in modo permanente l'elaborazione di un messaggio. È consentito eseguire qualsiasi altro codice. Solo quando arriva un messaggio, attiva una funzione che leggerà ed elaborerà questo messaggio.
https://riptutorial.com/it/home 200
Modalità 3: streaming ( tempo reale )
Ora scateniamo tutta la potenza del mio strumento. Lo metto in una modalità in cui invierà costantemente misurazioni alla linea seriale. Il mio programma desidera ricevere questi pacchetti e visualizzarli su una curva o su un display digitale. Se invia solo un valore ogni 5 secondi come sopra, nessun problema, mantieni la modalità precedente. Ma il mio strumento a pieno ritmo invia un punto dati alla linea seriale a 1000 Hz, cioè invia un nuovo valore ogni millisecondo. Se rimango nella modalità asincrona sopra descritta, c'è un alto rischio (in realtà una certezza garantita) che la funzione speciale che abbiamo definito per elaborare ogni nuovo pacchetto richiederà più di 1 ms per eseguirla (se si desidera tracciare o visualizzare il valore, le funzioni grafiche sono piuttosto lente, non considerando nemmeno il filtraggio o la trasmissione FFT del segnale). Significa che la funzione inizierà ad essere eseguita, ma prima che finisca, un nuovo pacchetto arriverà e attiverà di nuovo la funzione. La seconda funzione viene inserita in una coda per l'esecuzione e inizia solo quando viene eseguita la prima ... ma a questo punto sono arrivati alcuni nuovi pacchetti e ognuno ha inserito una funzione da eseguire nella coda. Puoi prevedere rapidamente il risultato: quando sto tracciando il quinto punto, ne ho già centinaia in attesa di essere tracciato anche ... il gui rallenta, alla fine si congela, lo stack cresce, i buffer si riempiono, finché qualcosa non dà. Alla fine ti rimane un programma completamente congelato o semplicemente uno in crash.
Per superare questo, disconnetteremo ulteriormente il collegamento di sincronizzazione tra il PC e lo strumento. Lasceremo che lo strumento invii i dati al proprio ritmo, senza attivare immediatamente una funzione ad ogni arrivo di pacchetto. Il buffer della porta seriale accumula solo i pacchetti ricevuti. Il PC raccoglierà i dati nel buffer solo a un ritmo che può gestire (un intervallo regolare, impostato sul lato PC), farà qualcosa con esso (mentre il buffer verrà ricaricato dallo strumento), quindi raccoglierà un nuovo batch di dati dal buffer ... e così via.
Riepilogo: in questa modalità, lo strumento invia continuamente dati, che vengono raccolti dal buffer della porta seriale. A intervalli regolari, il PC raccoglie i dati dal buffer e fa qualcosa con esso. Non esiste un collegamento di sincronizzazione tra il PC e lo strumento. Entrambi eseguono i loro compiti secondo i loro tempi.
https://riptutorial.com/it/home 201
Elaborazione automatica dei dati ricevuti da una porta seriale
Alcuni dispositivi collegati tramite una porta seriale inviano dati al programma a una velocità costante (dati di streaming) o inviano dati a intervalli imprevedibili. È possibile configurare la porta seriale per eseguire automaticamente una funzione per gestire i dati ogni volta che arriva. Questa è chiamata la "funzione di callback" per l'oggetto della porta seriale.
Esistono due proprietà della porta seriale che devono essere impostate per utilizzare questa funzione: il nome della funzione desiderata per il callback ( BytesAvailableFcn ) e la condizione che deve attivare l'esecuzione della funzione di callback ( BytesAvailableFcnMode ).
Esistono due modi per attivare una funzione di callback:
Quando un certo numero di byte è stato ricevuto sulla porta seriale (tipicamente usato per dati binari)
1.
Quando un certo carattere viene ricevuto sulla porta seriale (tipicamente usato per testo o dati ASCII)
2.
Le funzioni di callback hanno due argomenti di input obbligatori, chiamati obj e event . obj è la porta seriale. Ad esempio, se si desidera stampare i dati ricevuti dalla porta seriale, definire una funzione per stampare i dati chiamati newdata :
function newdata(obj,event) [d,c] = fread(obj); % get the data from the serial port % Note: for ASCII data, use fscanf(obj) to return characters instead of binary values fprintf(1,'Received %d bytes\n',c); disp(d) end
Ad esempio, per eseguire la funzione newdata ogni volta che vengono ricevuti 64 byte di dati, configurare la porta seriale in questo modo:
s = serial(port_name); s.BytesAvailableFcnMode = 'byte'; s.BytesAvailableFcnCount = 64; s.BytesAvailableFcn = @newdata;
https://riptutorial.com/it/home 202
Con dati di testo o ASCII, i dati sono generalmente divisi in righe con un "carattere di terminazione", proprio come il testo su una pagina. Per eseguire la funzione newdata ogni volta che viene ricevuto il carattere di ritorno a newdata , configurare la porta seriale in questo modo:
s = serial(port_name); s.BytesAvailableFcnMode = 'terminator'; s.Terminator = 'CR'; % the carriage return, ASCII code 13 s.BytesAvailableFcn = @newdata;
Leggi Usando le porte seriali online: https://riptutorial.com/it/matlab/topic/1176/usando-le-porte-seriali
https://riptutorial.com/it/home 203
Capitolo 31: Utility di programmazione
Examples
Semplice timer in MATLAB
Quello che segue è un timer che si attiva a intervalli fissi. Il timeout è definito da Period e richiama un callback definito da Timerfcn al timeout.
t = timer; t.TasksToExecute = Inf; t.Period = 0.01; % timeout value in seconds t.TimerFcn = @(myTimerObj, thisEvent)disp('hello'); % timer callback function t.ExecutionMode = 'fixedRate'; start(t) pause(inf);
Leggi Utility di programmazione online: https://riptutorial.com/it/matlab/topic/1655/utility-di-programmazione
https://riptutorial.com/it/home 204
Capitolo 32: Utilizzo della funzione `accumarray ()`
introduzione
accumarray consente di aggregare elementi di un array in vari modi, potenzialmente applicando alcune funzioni agli elementi nel processo. accumarray può essere pensato come un riduttore leggero (vedi anche: Introduzione a MapReduce ).
Questo argomento conterrà scenari comuni in cui accumarray è particolarmente utile.
Sintassi
accumarray (subscriptArray, valuesArray)•accumarray (subscriptArray, valuesArray, sizeOfOutput)•accumarray (subscriptArray, valuesArray, sizeOfOutput, funcHandle)•accumarray (subscriptArray, valuesArray, sizeOfOutput, funcHandle, fillVal)•accumarray (subscriptArray, valuesArray, sizeOfOutput, funcHandle, fillVal, isSparse)•
Parametri
Parametro Dettagli
subscriptArrayMatrice di pedici, specificata come vettore di indici, matrice di indici o matrice di celle di vettori di indice.
valuesArray Dati, specificati come vettore o scalare.
sizeOfOutputDimensione della matrice di output, specificata come vettore di numeri interi positivi.
funcHandleFunzione da applicare a ogni serie di elementi durante l'aggregazione, specificata come handle di funzione o [] .
fillValValore di riempimento, per quando i subs non fanno riferimento a ciascun elemento nell'output.
isSparse L'output dovrebbe essere un array sparse?
Osservazioni
Introdotto in MATLAB v7.0.•
https://riptutorial.com/it/home 205
Riferimenti :
"Under-apprezzato accumarray ", di Loren Shure , 20 febbraio 2008 .1. accumarray nella documentazione ufficiale di MATLAB.2.
Examples
Trovare il valore massimo tra gli elementi raggruppati da un altro vettore
Questo è un esempio ufficiale di MATLAB
Considera il seguente codice:
month = [1;1;2;3;8;1;3;4;9;11;9;12;3;4;11]; temperature = [57;61;60;62;45;59;64;66;40;56;38;65;61;64;55]; maxTemp = accumarray(month,temperature,[],@max);
L'immagine sotto mostra il processo di calcolo fatto da accumarray in questo caso:
In questo esempio, tutti i valori che hanno lo stesso month vengono prima raccolti e quindi la funzione specificata dal 4 ° input per accumarray (in questo caso, @max ) viene applicata a ciascun set.
Applica il filtro alle patch delle immagini e imposta ciascun pixel come media
https://riptutorial.com/it/home 206
del risultato di ciascuna patch
Molti moderni algoritmi di elaborazione delle immagini utilizzano le patch come elemento di base su cui lavorare. Ad esempio, è possibile eliminare le patch (vedere Algoritmo BM3D).
Tuttavia, quando costruisci l'immagine sotto forma di patch elaborate, abbiamo molti risultati per lo stesso pixel. Un modo per affrontarlo è prendere la media (media empirica) di tutti i valori dello stesso pixel.
Il seguente codice mostra come rompere un'immagine in patch e ricostruire l'immagine dalle patch usando la media usando [accumarray()][1] :
numRows = 5; numCols = 5; numRowsPatch = 3; numColsPatch = 3; % The Image mI = rand([numRows, numCols]); % Decomposing into Patches - Each pixel is part of many patches (Neglecting % boundariwes, each pixel is part of (numRowsPatch * numColsPatch) patches). mY = ImageToColumnsSliding(mI, [numRowsPatch, numColsPatch]); % Here one would apply some operation which work on patches % Creating image of the index of each pixel mPxIdx = reshape(1:(numRows * numCols), [numRows, numCols]); % Creating patches of the same indices mSubsAccu = ImageToColumnsSliding(mPxIdx, [numRowsPatch, numColsPatch]); % Reconstruct the image - Option A mO = accumarray(mSubsAccu(:), mY(:)) ./ accumarray(mSubsAccu(:), 1); % Reconstruct the image - Option B mO = accumarray(mSubsAccu, mY(:), [(numRows * numCols), 1], @(x) mean(x)); % Rehsape the Vector into the Image mO = reshape(mO, [numRows, numCols]);
Leggi Utilizzo della funzione `accumarray ()` online: https://riptutorial.com/it/matlab/topic/9321/utilizzo-della-funzione--accumarray----
https://riptutorial.com/it/home 207
Capitolo 33: Utilizzo di funzioni con output logico
Examples
Tutti e Tutti con array vuoti
È necessario prestare particolare attenzione quando esiste la possibilità che un array diventi un array vuoto quando si tratta di operatori logici. Spesso è previsto che se all(A) è vero allora any(A) deve essere vero e se any(A) è falso, anche all(A) deve essere falso. Questo non è il caso in MATLAB con array vuoti.
>> any([]) ans = 0 >> all([]) ans = 1
Quindi, se per esempio stai confrontando tutti gli elementi di una matrice con una certa soglia, devi essere consapevole del caso in cui la matrice è vuota:
>> A=1:10; >> all(A>5) ans = 0 >> A=1:0; >> all(A>5) ans = 1
Utilizzare la funzione built-in è isempty per verificare la presenza di array vuoti:
a = []; isempty(a) ans = 1
Leggi Utilizzo di funzioni con output logico online: https://riptutorial.com/it/matlab/topic/5608/utilizzo-di-funzioni-con-output-logico
https://riptutorial.com/it/home 208
Capitolo 34: vettorializzazione
Examples
Operazioni elementali
MATLAB supporta (e incoraggia) operazioni vettorializzate su vettori e matrici. Ad esempio, supponiamo di avere A e B , due n -by- m matrici e vogliamo C sia il prodotto elemento-saggio degli elementi corrispondenti (ad esempio, C(i,j) = A(i,j)*B(i,j) ).
Il modo non-vettorizzato, usando i cicli annidati è il seguente:
C = zeros(n,m); for ii=1:n for jj=1:m C(ii,jj) = A(ii,jj)*B(ii,jj); end end
Tuttavia, il modo vettoriale per farlo è usando l'operatore element-wise .* :
C = A.*B;
Per ulteriori informazioni sulla moltiplicazione degli elementi in MATLAB consultare la documentazione dei times .
•
Per ulteriori informazioni sulla differenza tra le operazioni su matrice e matrice, consultare Array vs. Matrix Operations nella documentazione di MATLAB.
•
Somma, significa, prod & co
Dato un vettore casuale
v = rand(10,1);
se vuoi la somma dei suoi elementi, NON usare un ciclo
s = 0; for ii = 1:10 s = s + v(ii); end
ma usa la capacità vettoriale della funzione sum()
s = sum(v);
https://riptutorial.com/it/home 209
Funzioni come sum() , mean() , prod() e altri, hanno la capacità di operare direttamente lungo righe, colonne o altre dimensioni.
Ad esempio, data una matrice casuale
A = rand(10,10);
la media per ogni colonna è
m = mean(A,1);
la media per ogni riga è
m = mean(A,2)
Tutte le funzioni sopra funzionano solo su una dimensione, ma cosa succede se vuoi sommare l'intera matrice? Potresti usare:
s = sum(sum(A))
Ma cosa succede se hai un ND-array? applicare la sum sulla sum sulla sum ... non sembra l'opzione migliore, invece usa l'operatore : per vettorizzare il tuo array:
s = sum(A(:))
e questo si tradurrà in un numero che è la somma di tutto il tuo array, non importa quante dimensioni ha.
Uso di bsxfun
Molto spesso, il motivo per cui il codice è stato scritto in un ciclo for consiste nel calcolare valori da quelli 'vicini'. La funzione bsxfun può essere usata spesso per farlo in un modo più succinto.
Ad esempio, si supponga di voler eseguire un'operazione a colonna sulla matrice B , sottraendo la media di ogni colonna da essa:
B = round(randn(5)*10); % Generate random data A = zeros(size(B)); % Preallocate array for col = 1:size(B,2); % Loop over columns A(:,col) = B(:,col) - mean(B(:,col)); % Subtract means end
Questo metodo è inefficiente se B è grande, spesso a causa del fatto che MATLAB deve spostare il contenuto delle variabili attorno alla memoria. Usando bsxfun , si può fare lo stesso lavoro ordinatamente e facilmente in una sola riga:
A = bsxfun(@minus, B, mean(B));
https://riptutorial.com/it/home 210
Qui, @minus è una funzione che gestisce l'operatore minus ( - ) e verrà applicata tra gli elementi delle due matrici B e mean(B) . Sono possibili anche altre maniglie di funzione, anche quelle definite dall'utente.
Successivamente, si supponga di voler aggiungere il vettore di riga v a ciascuna riga nella matrice A :
v = [1, 2, 3]; A = [8, 1, 6 3, 5, 7 4, 9, 2];
L'approccio ingenuo è usare un ciclo ( non farlo ):
B = zeros(3); for row = 1:3 B(row,:) = A(row,:) + v; end
Un'altra opzione sarebbe quella di replicare v con repmat ( non farlo neanche ):
>> v = repmat(v,3,1) v = 1 2 3 1 2 3 1 2 3 >> B = A + v;
Usa invece bsxfun per questa attività:
>> B = bsxfun(@plus, A, v); B = 9 3 9 4 7 10 5 11 5
Sintassi
bsxfun(@fun, A, B)
dove @fun è una delle funzioni supportate e i due array A e B rispettano le due condizioni seguenti.
Il nome bsxfun aiuta a capire come funziona la funzione e si distingue per la B ction FUN fabbrica di alcune componenti con S Ingleton e X pansion. In altre parole, se:
due array condividono le stesse dimensioni tranne uno1. e la dimensione discordante è un singleton (cioè ha una dimensione di 1 ) in uno dei due array
2.
https://riptutorial.com/it/home 211
quindi l'array con la dimensione Singleton verrà espanso per corrispondere alla dimensione dell'altro array. Dopo l'espansione, una funzione binaria viene applicata elementwise sui due array.
Ad esempio, sia A un array M -by- N -by K e B sia un array M -by- N . In primo luogo, le loro prime due dimensioni hanno dimensioni corrispondenti. In secondo luogo, A ha livelli K mentre B ha implicitamente solo 1 , quindi è un singleton. Tutte le condizioni sono soddisfatte e B verrà replicato per corrispondere alla 3a dimensione di A
In altre lingue, questo è comunemente chiamato trasmissione e avviene automaticamente in Python (numpy) e Octave.
La funzione, @fun , deve essere una funzione binaria che significa che deve prendere esattamente due input.
Osservazioni
Internamente, bsxfun non replica la matrice ed esegue un ciclo efficiente.
Mascheramento logico
MATLAB supporta l'uso del mascheramento logico per eseguire la selezione su una matrice senza l'uso di cicli for o di istruzioni.
Una maschera logica è definita come una matrice composta solo da 1 e 0 .
Per esempio:
mask = [1 0 0; 0 1 0; 0 0 1];
è una matrice logica che rappresenta la matrice di identità.
Possiamo generare una maschera logica usando un predicato per interrogare una matrice.
A = [1 2 3; 4 5 6; 7 8 9]; B = A > 4;
Per prima cosa creiamo una matrice 3x3, A , contenente i numeri da 1 a 9. Quindi interrogiamo A per valori maggiori di 4 e memorizziamo il risultato in una nuova matrice chiamata B
B è una matrice logica della forma:
B = [0 0 0 0 1 1 1 1 1]
O 1 quando il predicato A > 4 era vero. E 0 quando era falso.
Possiamo usare matrici logiche per accedere agli elementi di una matrice. Se si utilizza una
https://riptutorial.com/it/home 212
matrice logica per selezionare gli elementi, gli indici in cui 1 appare nella matrice logica saranno selezionati nella matrice da cui si sta selezionando.
Usando la stessa B dall'alto, potremmo fare quanto segue:
C = [0 0 0; 0 0 0; 0 0 0]; C(B) = 5;
Questo selezionerebbe tutti gli elementi di C cui B ha un 1 in quell'indice. Questi indici in C sono quindi impostati su 5 .
La nostra C ora sembra:
C = [0 0 0 0 5 5 5 5 5]
Possiamo ridurre complicati blocchi di codice contenenti if e for utilizzando maschere logiche.
Prendi il codice non-vettorizzato:
A = [1 3 5; 7 9 11; 11 9 7]; for j = 1:length(A) if A(j) > 5 A(j) = A(j) - 2; end end
Questo può essere abbreviato usando il mascheramento logico al seguente codice:
A = [1 3 5; 7 9 11; 11 9 7]; B = A > 5; A(B) = A(B) - 2;
O ancora più corto:
A = [1 3 5; 7 9 11; 11 9 7]; A(A > 5) = A(A > 5) - 2;
Espansione di array implicita (broadcasting) [R2016b]
MATLAB R2016b presentava una generalizzazione del suo meccanismo di espansione scalare 1 ,
2 , per supportare anche certe operazioni element-grade tra array di diverse dimensioni, purché le loro dimensioni fossero compatibili. Gli operatori che supportano l'espansione implicita sono 1 :
Operatori aritmetici element-wise: + , - ./ .* ./ .^ , ./ .\ .•Operatori relazionali: < , <= , > , >= , == , ~= .•Operatori logici: & , | , xor .•Funzioni bit-bit: bitand , bitor , bitxor .•Funzioni matematiche elementari: max , min , mod , rem , hypot , atan2 , atan2d .•
https://riptutorial.com/it/home 213
Le suddette operazioni binarie sono consentite tra gli array, purché abbiano "dimensioni compatibili". Le dimensioni sono considerate "compatibili" quando ogni dimensione in un array è esattamente uguale alla stessa dimensione nell'altro array o è uguale a 1 . Nota che le dimensioni finali di singleton (ovvero di dimensione 1 ) sono omesse da MATLAB, anche se teoricamente c'è una quantità infinita di esse. In altre parole - le dimensioni che compaiono in una matrice e non compaiono nell'altra, sono implicitamente idonee per l'espansione automatica.
Ad esempio, nelle versioni MATLAB precedenti a R2016b ciò accadrebbe:
>> magic(3) + (1:3) Error using + Matrix dimensions must agree.
Mentre a partire da R2016b l'operazione precedente avrà esito positivo:
>> magic(3) + (1:3) ans = 9 3 9 4 7 10 5 11 5
Esempi di dimensioni compatibili:
Descrizione1ª dimensione di matrice
2 ° dimensione array
Dimensione del risultato
Vettore e scalare [3x1] [1x1] [3x1]
Vettori di righe e colonne
[1x3] [2x1] [2x3]
Matrice vettoriale e 2D
[1x3] [5x3] [5x3]
Array ND e KD [1x3x3] [5x3x1x4x2] [5x3x3x4x2]
Esempi di dimensioni incompatibili:
https://riptutorial.com/it/home 214
Descrizione1ª dimensione di matrice
2 ° dimensione array
Possibile soluzione
Vettori in cui una dimensione è un multiplo della stessa dimensione nell'altra matrice.
[1x2] [1x8] transpose
Array con dimensioni che sono multipli l'uno dell'altro.
[2x2] [8x8] repmat , reshape
Matrici ND che hanno la giusta quantità di dimensioni singleton ma sono nell'ordine sbagliato (n. 1).
[2x3x4] [2x4x3] permute
Matrici ND che hanno la giusta quantità di dimensioni singleton ma sono nell'ordine sbagliato (n. 2).
[2x3x4x5] [5x2] permute
IMPORTANTE: Il codice basato su questa convenzione NON è retrocompatibile con le versioni precedenti di MATLAB. Pertanto, l'invocazione esplicita di bsxfun 1 , 2 (che ottiene lo stesso effetto) dovrebbe essere utilizzata se il codice deve essere eseguito su versioni MATLAB precedenti. Se tale preoccupazione non esiste, le note sulla versione MATLAB R2016 incoraggiano gli utenti a passare da bsxfun :
Rispetto all'utilizzo di bsxfun , l'espansione implicita offre una maggiore velocità di esecuzione, un migliore utilizzo della memoria e una migliore leggibilità del codice.
Lettura correlata:
Documentazione MATLAB su " Dimensioni di array compatibili per operazioni di base ".•NumPy's Broadcasting 1 , 2 .•Un confronto tra la velocità del calcolo usando bsxfun vs. espansione di array implicita .•
Ottieni il valore di una funzione di due o più argomenti
In molte applicazioni è necessario calcolare la funzione di due o più argomenti.
Tradizionalmente, usiamo for -loops. Ad esempio, se abbiamo bisogno di calcolare il valore f = exp(-x^2-y^2) (non usare questo se hai bisogno di simulazioni veloci ):
% code1 x = -1.2:0.2:1.4; y = -2:0.25:3; for nx=1:lenght(x) for ny=1:lenght(y) f(nx,ny) = exp(-x(nx)^2-y(ny)^2); end
https://riptutorial.com/it/home 215
end
Ma la versione vettoriale è più elegante e veloce:
% code2 [x,y] = ndgrid(-1.2:0.2:1.4, -2:0.25:3); f = exp(-x.^2-y.^2);
di quanto possiamo visualizzare:
surf(x,y,f)
Nota 1 - Griglie: in genere, la memoria della matrice è organizzata riga per riga . Ma nel MATLAB, è l'archiviazione colonna per colonna come in FORTRAN. Quindi, ci sono due funzioni ndgrid e meshgrid in MATLAB per implementare i due modelli sopra menzionati. Per visualizzare la funzione nel caso di meshgrid , possiamo usare:
surf(y,x,f)
Nota 2 - Il consumo di memoria: Let dimensioni di x o y è 1000. In questo modo, abbiamo bisogno di memorizzare 1000*1000+2*1000 ~ 1e6 elementi per code1 non vectorized. Ma abbiamo bisogno di 3*(1000*1000) = 3e6 elementi nel caso di code2 vettorializzare. Nel caso 3D (lasciare che z abbia le stesse dimensioni di x o y ), il consumo di memoria aumenta drammaticamente: 4*(1000*1000*1000) (~ 32 GB per i doppi) nel caso del codice 2 vettorizzato vs ~1000*1000*1000 (solo ~ 8 GB) nel caso di code1 . Quindi, dobbiamo scegliere la memoria o la velocità.
Leggi vettorializzazione online: https://riptutorial.com/it/matlab/topic/750/vettorializzazione
https://riptutorial.com/it/home 216
Titoli di coda
S. No
Capitoli Contributors
1Iniziare con MATLAB Language
adjpayot, Amro, chrisb2244, Christopher Creutzig, Community, Dan, Dev-iL, DVarga, EBH, Erik, excaza, flawr, Franck Dernoncourt, fyrepenguin, GameOfThrows, H. Pauwelyn, honi, Landak, Lior, Matt, Mikhail_Sam, Mohsen Nosratinia, Sam Roberts, Shai, Tyler
2Applicazioni finanziarie
Amro, Franck Dernoncourt, Mikhail_Sam, Oleg, Royi, StefanM
3Best practice di MATLAB
il_raffa, Malick, MayeulC, McLemon, mnoronha, NKN, rayryeng, Sardar Usama, Thierry Dalon
4 condizioni ammportal, EBH
5Controllo della colorazione di sottotrama in Matlab
Noa Regev
6 Debug Dev-iL, DVarga, jenszvs, Justin
7 Disegno il_raffa, nitsua60, NKN, thewaywewalk, Trilarion, Zep
8Elaborazione delle immagini
A.Youssouf, Ander Biguri, Cape Code, girish_m, Royi, Shai, Trilarion
9 Errori e errori comuni
Amro, Ander Biguri, Dev-iL, EBH, edwinksl, erfan, Franck Dernoncourt, Hoki, Landak, Malick, Matt, Mikhail_Sam, Mohsen Nosratinia, nahomyaja, NKN, Oleg, R. Joiny, rafa, rayryeng, Rody Oldenhuis, S. Radev, Sardar Usama, strpeter, Suever, Thierry Dalon, Tim, Umar
10Funzionalità non documentate
Amro, codeaviator, Dev-iL, Erik, matlabgui, thewaywewalk
11 funzioni Batsu
12Funzioni di documentazione
alexforrence, Ander Biguri, ceiltechbladhm, Dev-iL, Eric, excaza
13Grafica: grafici a linee 2D
Amro, Celdor, EBH, Erik, Matt, Oleg, StefanM
Grafica: 14 itzik Ben Shabat, Royi
https://riptutorial.com/it/home 217
trasformazioni 2D e 3D
15Imposta le operazioni
Shai, StefanM
16Inizializzazione di matrici o array
Parag S. Chandakkar, rajah9, Théo P.
17 Integrazione StefanM
18Interfacce utente MATLAB
Dev-iL, Hoki, Royi, Suever, Zep
19Interpolazione con MATLAB
Royi, StefanM
20Introduzione all'API MEX
Amro, Ander Biguri, Kamiccolo, Matt, mike
21Lettura di file di grandi dimensioni
JCKaz
22 multithreadingAdriaan, daren shan, Franck Dernoncourt, Hardik_Jain, Jim, Peter Mortensen
23 Per i loop agent_C.Hdj, drhagen, EBH, Tyler
24Prestazioni e Benchmarking
Celdor, daleonpz, Dev-iL, il_raffa, Oleg, pseudoDust, thewaywewalk
25Programmazione orientata agli oggetti
alexforrence, Celdor, daren shan, Dev-iL, jenszvs, Mohsen Nosratinia, Trogdor
26
Risolutori di equazioni differenziali ordinarie (ODE)
Royi, StefanM
27Scomposizioni della matrice
StefanM
28
Trasformate di Fourier e Trasformate di Fourier inverse
GameOfThrows, Landak
29 Trucchi utili Celdor, EBH, Erik, fyrepenguin, Malick
Usando le porte Abdul Rehman, Ander Biguri, Hoki, Kenn Sebesta, mhopeng, 30
https://riptutorial.com/it/home 218
seriali Oleg
31Utility di programmazione
Celdor, The Vivandiere
32Utilizzo della funzione `accumarray ()`
Dev-iL, Royi
33Utilizzo di funzioni con output logico
Landak, Mikhail_Sam, Mohsen Nosratinia, S. Radev, Trilarion
34 vettorializzazioneAlexander Korovin, Ander Biguri, Dan, Dev-iL, EBH, Landak, Matt, Oleg, Shai, Tyler
https://riptutorial.com/it/home 219