MATLAB Language
Errori e errori comuni
Ricerca…
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 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 =
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:
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.
È 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.
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
edy
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
, ovveroN*eps(max(x,y))
, doveN
è un numero specifico del problema. Una scelta ragionevole perN
, che è anche abbastanza permissiva, è1E2
(anche se, nel problema precedenteN=1
sarebbe anche sufficiente).
Ulteriori letture:
Consulta queste domande per ulteriori informazioni sull'input di virgola mobile:
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 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);
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
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 dii
ej
per i nomi di variabili se si intende usarli in aritmetica complessa.- Per velocità e robustezza migliorata in aritmetica complessa, usa
1i
e1j
invece dii
ej
.
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)
.
>> 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:
>> 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
oj
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 =
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.
- La più grande dimensione del vettore.
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 diA
-
numel(A)
- restituisce il numero di elementi inA
Equivalente aprod(size(A))
. -
ndims(A)
- restituisce il numero di dimensioni nell'arrayA
Equivalente alnumel(size(A))
.
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.