MATLAB Language
Typowe błędy i pomyłki
Szukaj…
Nie nazywaj zmiennej istniejącą nazwą funkcji
Istnieje już funkcja sum()
. W rezultacie, jeśli nazwiemy zmienną o tej samej nazwie
sum = 1+3;
i jeśli spróbujemy użyć funkcji, gdy zmienna nadal istnieje w obszarze roboczym
A = rand(2);
sum(A,1)
otrzymamy tajemniczy błąd :
Subscript indices must either be real positive integers or logicals.
najpierw clear()
zmienną, a następnie użyj funkcji
clear sum
sum(A,1)
ans =
1.0826 1.0279
Jak możemy sprawdzić, czy funkcja już istnieje, aby uniknąć tego konfliktu?
Użyj which()
z flagą -all
:
which sum -all
sum is a variable.
built-in (C:\Program Files\MATLAB\R2016a\toolbox\matlab\datafun\@double\sum) % Shadowed double method
...
To wyjście mówi nam, że sum
jest najpierw zmienną i że następujące metody (funkcje) są przez nią zasłaniane, tj. MATLAB najpierw spróbuje zastosować naszą składnię do zmiennej, zamiast używać tej metody.
To, co widzisz, NIE jest tym, co dostajesz: char vs cellstring w oknie poleceń
To podstawowy przykład skierowany do nowych użytkowników. Nie skupia się na wyjaśnieniu różnicy między char
a cellstring
.
Może się zdarzyć, że chcesz pozbyć się '
ciągów”, chociaż nigdy ich nie dodałeś. W rzeczywistości są to artefakty , których używa okno poleceń do rozróżniania niektórych typów.
Napis zostanie wydrukowany
s = 'dsadasd'
s =
dsadasd
Zostanie wydrukowany ciąg komórek
c = {'dsadasd'};
c =
'dsadasd'
Zwróć uwagę, że pojedyncze cudzysłowy i wcięcia są artefaktami, które powiadamiają nas, że c
jest cellstring
a nie char
. Ciąg jest w rzeczywistości zawarty w komórce, tj
c{1}
ans =
dsadasd
Operatory transpozycji
-
.'
jest prawidłowym sposobem transponowania wektora lub macierzy w MATLAB. -
'
jest prawidłowym sposobem przyjęcia złożonej transpozycji koniugatu (inaczej koniugatu hermitowskiego) wektora lub macierzy w MATLAB.
Uwaga: w przypadku transpozycji .'
, przed apostrofem jest okres . Jest to zgodne ze składnią innych operacji elementarnych w MATLAB: *
zwielokrotnia macierze,. .*
Zwielokrotnia elementy macierzy razem. Te dwa polecenia są bardzo podobne, ale koncepcyjnie bardzo różne. Podobnie jak inne polecenia MATLAB, operatory te są „cukrem syntaktycznym”, który zamienia się w „właściwe” wywołanie funkcji w czasie wykonywania. Podobnie jak ==
staje się oceną funkcji eq , pomyśl o .'
jako skrót do transpose
. Jeśli napiszesz tylko '
(bez sensu), w rzeczywistości zamiast tego ctranspose
polecenia ctranspose
, które oblicza złożoną transpozycję sprzężoną , znaną również jako koniugat hermitowski , często używany w fizyce. Tak długo, jak transponowany wektor lub matryca ma wartość rzeczywistą, oba operatory dają ten sam wynik. Ale gdy tylko zajmiemy się liczbami zespolonymi , nieuchronnie napotkamy problemy, jeśli nie użyjemy „poprawnego” skrótu. To, co jest „prawidłowe”, zależy od twojej aplikacji.
Rozważ następujący przykład macierzy C
zawierającej liczby zespolone:
>> C = [1i, 2; 3*1i, 4]
C =
0.0000 + 1.0000i 2.0000 + 0.0000i
0.0000 + 3.0000i 4.0000 + 0.0000i
Weźmy transpozycję za pomocą stenografii .'
(z okresem). Wynik jest zgodny z oczekiwaniami, transponowana forma C
>> C.'
ans =
0.0000 + 1.0000i 0.0000 + 3.0000i
2.0000 + 0.0000i 4.0000 + 0.0000i
Teraz użyjmy '
(bez kropki). Widzimy, że oprócz transpozycji wartości zespolone zostały również przekształcone w ich złożone koniugaty .
>> C'
ans =
0.0000 - 1.0000i 0.0000 - 3.0000i
2.0000 + 0.0000i 4.0000 + 0.0000i
Podsumowując, jeśli zamierzasz obliczyć koniugat hermitowski, transponuj koniugat złożony, użyj '
(bez kropki). Jeśli chcesz tylko obliczyć transpozycję bez koniugacji zespolonej wartości, użyj .'
(z okresem).
Niezdefiniowana funkcja lub metoda X dla argumentów wejściowych typu Y
Jest to długi sposób MATLAB-a, który mówi, że nie może znaleźć funkcji, którą próbujesz wywołać. Istnieje wiele powodów, dla których można uzyskać ten błąd:
Ta funkcja została wprowadzona po twojej bieżącej wersji MATLAB
Dokumentacja online MATLAB zapewnia bardzo miłą funkcję, która pozwala określić, w jakiej wersji została wprowadzona dana funkcja. Znajduje się w lewym dolnym rogu każdej strony dokumentacji:
Porównaj tę wersję z własną bieżącą wersją ( ver
), Aby ustalić, czy ta funkcja jest dostępna w konkretnej wersji. Jeśli nie, spróbuj przeszukać zarchiwizowane wersje dokumentacji, aby znaleźć odpowiednią alternatywę dla swojej wersji.
Nie masz tego zestawu narzędzi!
Podstawowa instalacja MATLAB ma wiele funkcji; jednak bardziej wyspecjalizowane funkcje są pakowane w skrzynki narzędziowe i sprzedawane osobno przez Mathworks. Dokumentacja wszystkich zestawów narzędzi jest widoczna niezależnie od tego, czy masz zestaw narzędzi, czy nie, więc sprawdź i sprawdź, czy masz odpowiedni zestaw narzędzi.
Aby sprawdzić, do którego przybornika należy dana funkcja, spójrz w lewy górny róg dokumentacji online, aby sprawdzić, czy wymieniono określony przybornik.
Następnie możesz określić, które skrzynki narzędziowe zainstalowała Twoja wersja MATLAB, wydając komendę ver
która wyświetli listę wszystkich zainstalowanych skrzynek narzędziowych.
Jeśli nie masz zainstalowanego tego przybornika i chcesz korzystać z tej funkcji, musisz kupić licencję na ten konkretny przybornik od Mathworks.
MATLAB nie może zlokalizować funkcji
Jeśli MATLAB nadal nie może znaleźć twojej funkcji, musi to być funkcja zdefiniowana przez użytkownika. Możliwe, że znajduje się on w innym katalogu i katalog ten powinien zostać dodany do ścieżki wyszukiwania w celu uruchomienia kodu. Możesz sprawdzić, czy MATLAB może zlokalizować twoją funkcję, używając which
który powinien zwrócić ścieżkę do pliku źródłowego.
Uważaj na niedokładność zmiennoprzecinkową
Liczby zmiennoprzecinkowe nie mogą reprezentować wszystkich liczb rzeczywistych. Jest to znane jako niedokładność zmiennoprzecinkowa.
Istnieje nieskończenie wiele liczb zmiennoprzecinkowych i mogą być nieskończenie długie (np. π
), dlatego ich perfekcyjne przedstawienie wymagałoby nieskończenie dużej ilości pamięci. Widząc, że był to problem, zaprojektowano specjalną reprezentację pamięci „rzeczywistej” w komputerze, standard IEEE 754 . W skrócie opisuje, w jaki sposób komputery przechowują ten typ liczb, z wykładnikiem i mantysą, jak:
floatnum = sign * 2^exponent * mantissa
Przy ograniczonej ilości bitów dla każdego z nich można osiągnąć tylko skończoną precyzję. Im mniejsza liczba, tym mniejsza różnica między możliwymi liczbami (i odwrotnie!). Możesz wypróbować swoje prawdziwe liczby w tym demo online .
Bądź świadomy tego zachowania i staraj się unikać porównywania wszystkich zmiennych zmiennoprzecinkowych i ich wykorzystania jako warunków zatrzymania w pętlach. Zobacz poniżej dwa przykłady:
Przykłady: porównanie zmiennoprzecinkowe wykonane ŹLE:
>> 0.1 + 0.1 + 0.1 == 0.3
ans =
logical
0
Złą praktyką jest porównywanie zmiennoprzecinkowe, jak pokazano w poprzednim przykładzie. Możesz temu zaradzić, przyjmując bezwzględną wartość różnicy i porównując ją z (małym) poziomem tolerancji.
Poniżej znajduje się inny przykład, w którym liczba zmiennoprzecinkowa jest używana jako warunek zatrzymania w pętli while: **
k = 0.1;
while k <= 0.3
disp(num2str(k));
k = k + 0.1;
end
% --- Output: ---
0.1
0.2
Brakuje ostatniej oczekiwanej pętli ( 0.3 <= 0.3
).
Przykład: porównanie zmiennoprzecinkowe wykonane PRAWO:
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
Kilka rzeczy do zapamiętania:
- Zgodnie z oczekiwaniami, obecnie
x
iy
są traktowane jako równoważne. - W powyższym przykładzie wybór tolerancji został dokonany arbitralnie. Dlatego wybrana wartość może nie być odpowiednia dla wszystkich przypadków (szczególnie przy pracy ze znacznie mniejszymi liczbami). Inteligentnego wyboru granicy można dokonać za pomocą funkcji
eps
, tj.N*eps(max(x,y))
, gdzieN
jest liczbą specyficzną dla problemu. Rozsądnym wyborem dlaN
, który jest również wystarczająco liberalny, jest1E2
(chociaż w powyższym problemieN=1
również by wystarczyło).
Dalsza lektura:
Zobacz następujące pytania, aby uzyskać więcej informacji o niedokładności zmiennoprzecinkowej:
Za mało argumentów wejściowych
Często początkujący programiści MATLAB używają edytora MATLAB do pisania i edycji kodu, w szczególności niestandardowych funkcji z wejściami i wyjściami. Na górze znajduje się przycisk Uruchom , który jest dostępny w najnowszych wersjach MATLAB:
Gdy programista kończy kod, często kusi go, aby nacisnąć przycisk Uruchom . W przypadku niektórych funkcji będzie to działać poprawnie, ale w przypadku innych wystąpi błąd Za Not enough input arguments
i będą zastanawiać się, dlaczego wystąpił błąd.
Przyczyną tego błędu może nie być to, że napisałeś skrypt MATLAB lub funkcję, która nie przyjmuje żadnych argumentów wejściowych. Użycie przycisku Uruchom spowoduje uruchomienie skryptu testowego lub funkcji przy założeniu braku argumentów wejściowych. Jeśli twoja funkcja wymaga argumentów wejściowych, wystąpi błąd Not enough input arguments
ponieważ napisałeś funkcje, które oczekują, że dane Not enough input arguments
wejdą do funkcji. Dlatego nie można oczekiwać, że funkcja będzie działać, po prostu naciskając przycisk Uruchom .
Aby zademonstrować ten problem, załóżmy, że mamy funkcję mult
która po prostu mnoży dwie macierze razem:
function C = mult(A, B)
C = A * B;
end
W najnowszych wersjach MATLAB, jeśli napisałeś tę funkcję i nacisnąłeś przycisk Uruchom , wyświetli się oczekiwany błąd:
>> mult
Not enough input arguments.
Error in mult (line 2)
C = A * B;
Istnieją dwa sposoby rozwiązania tego problemu:
Metoda nr 1 - Za pomocą wiersza polecenia
Po prostu utwórz potrzebne dane w wierszu polecenia, a następnie uruchom funkcję, korzystając z utworzonych danych:
A = rand(5,5);
B = rand(5,5);
C = mult(A,B);
Metoda nr 2 - Interaktywnie poprzez edytor
Pod przyciskiem Run znajduje się ciemna czarna strzałka. Po kliknięciu tej strzałki możesz określić zmienne, które chcesz uzyskać z obszaru roboczego MATLAB, wpisując sposób, w jaki chcesz wywołać funkcję dokładnie tak, jak to widzieliście w metodzie nr 1. Upewnij się, że zmienne określone w funkcji istnieją w obszarze roboczym MATLAB:
Uważaj na zmiany rozmiaru tablicy
Niektóre typowe operacje w MATLAB, takie jak różnicowanie lub integracja , dają wyniki, które mają inną liczbę elementów niż dane wejściowe. Fakt ten można łatwo przeoczyć, co zwykle powoduje błędy, takie jak Matrix dimensions must agree
. Rozważ następujący przykład:
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)
Powiedzmy, że chcemy wykreślić te wyniki. Przyjrzymy się rozmiarom tablic i zobaczymy:
size(y) is 1x101
size(t) is 1x101
Ale:
size(dy_dt) is 1x100
Tablica jest o jeden element krótsza!
Teraz wyobraź sobie, że masz dane pomiarowe pozycji w czasie i chcesz obliczyć szarpnięcie (t) , otrzymasz tablicę o 3 elementy mniej niż tablica czasu (ponieważ szarpnięcie jest pozycją różnicowaną 3 razy).
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
A następnie operacje takie jak:
x = jerk .* t; % multiplies jerk and t element wise
zwracają błędy, ponieważ wymiary matrycy się nie zgadzają.
Aby obliczyć operacje jak wyżej, musisz dopasować większy rozmiar tablicy, aby pasował do mniejszego. Możesz również uruchomić regresję ( polyfit
) z danymi, aby uzyskać wielomian dla danych.
Błędy niedopasowania wymiarów
Błędy niedopasowania wymiarów pojawiają się zwykle, gdy:
- Nie zwracanie uwagi na kształt zwracanych zmiennych z wywołań funkcji / metod. W wielu wbudowanych funkcjach MATLAB macierze są konwertowane na wektory w celu przyspieszenia obliczeń, a zwracana zmienna może nadal być wektorem, a nie oczekiwaną macierzą. Jest to również częsty scenariusz, w którym występuje maskowanie logiczne .
- Używanie niekompatybilnych rozmiarów tablic przy wywoływaniu niejawnego rozszerzenia tablicy .
Zastosowanie „i” lub „j” jako jednostki urojonej, wskaźników pętli lub wspólnej zmiennej.
Rekomendacje
Ponieważ symbole i
i j
mogą reprezentować znacznie różne rzeczy w MATLAB, ich użycie jako indeksów pętli od wieków dzieli społeczność użytkowników MATLAB. Chociaż niektóre historyczne przyczyny wydajności mogą pomóc w odchyleniu się na bok, nie jest to już prawdą, a teraz wybór zależy wyłącznie od ciebie i praktyk kodowania, których chcesz przestrzegać.
Aktualne oficjalne zalecenia Mathworks to:
- Ponieważ
i
jest funkcją, można ją zastąpić i użyć jako zmiennej. Jednak najlepiej jest unikać używaniai
ij
dla nazw zmiennych, jeśli zamierzasz używać ich w złożonej arytmetyce.- Aby uzyskać szybkość i większą odporność na złożoną arytmetykę, użyj
1i
i1j
zamiasti
ij
.
Domyślna
W MATLAB domyślnie litery i
oraz j
są wbudowanymi nazwami function
, które odnoszą się do jednostki urojonej w domenie złożonej.
Więc domyślnie i = j = sqrt(-1)
.
>> i
ans =
0.0000 + 1.0000i
>> j
ans =
0.0000 + 1.0000i
i jak można się spodziewać:
>> i^2
ans =
-1
Używanie ich jako zmiennej (dla indeksów pętli lub innej zmiennej)
MATLAB pozwala na użycie wbudowanej nazwy funkcji jako zmiennej standardowej. W takim przypadku użyty symbol nie będzie już wskazywał na funkcję wbudowaną, ale na zmienną zdefiniowaną przez użytkownika. Ta praktyka nie jest jednak generalnie zalecana, ponieważ może prowadzić do zamieszania, trudnych debugowania i konserwacji ( patrz inny przykład : nie-nazwa-zmiennej-z-istniejącą nazwą funkcji ).
Jeśli jesteś wyjątkowo pedantyczny, jeśli chodzi o przestrzeganie konwencji i najlepszych praktyk, unikniesz ich używania jako wskaźników pętli w tym języku. Jest to jednak dozwolone przez kompilator i doskonale funkcjonalne, więc możesz również zachować stare nawyki i używać ich jako iteratorów pętli.
>> A = nan(2,3);
>> for i=1:2 % perfectly legal loop construction
for j = 1:3
A(i, j) = 10 * i + j;
end
end
Zauważ, że indeksy pętli nie wychodzą poza zakres na końcu pętli, więc zachowują swoją nową wartość.
>> [ i ; j ]
ans =
2
3
Jeśli używasz ich jako zmiennych, upewnij się, że zostały one zainicjowane przed ich użyciem. W powyższej pętli MATLAB inicjuje je automatycznie podczas przygotowywania pętli, ale jeśli nie zostanie poprawnie zainicjowany, szybko zauważysz, że możesz przypadkowo wprowadzić liczby complex
do wyniku.
Jeśli później musisz cofnąć cienie wbudowanej funkcji (= np. Chcesz, aby i
i j
ponownie reprezentowały urojoną jednostkę), możesz clear
zmienne:
>> clear i j
Rozumiesz teraz zastrzeżenie Mathworks dotyczące używania ich jako wskaźników pętli, jeśli zamierzasz używać ich w złożonej arytmetyce . Twój kod byłby pełen różnorodnych inicjalizacji i clear
poleceń, najlepszy sposób na pomylenie najpoważniejszego programisty ( tak, ty tam! ... ) i wypadki programowe czekające na zdarzenie.
Jeśli nie oczekuje się złożonej arytmetyki, użycie i
i j
jest doskonale funkcjonalne i nie ma negatywnego wpływu na wydajność.
Używając ich jako wyimaginowanej jednostki:
Jeśli twój kod ma do czynienia z liczbami complex
, wtedy i
i j
pewno się przydadzą. Jednak ze względu na jednoznaczność, a nawet występy, zaleca się stosowanie pełnej formy zamiast składni stenografii. Pełna forma to 1i
(lub 1j
).
>> [ i ; j ; 1i ; 1j]
ans =
0.0000 + 1.0000i
0.0000 + 1.0000i
0.0000 + 1.0000i
0.0000 + 1.0000i
Reprezentują tę samą wartość sqrt(-1)
, ale późniejsza forma:
- jest bardziej wyraźny, w sposób semantyczny.
- jest łatwiejsza w utrzymaniu (ktoś, kto patrzy na twój kod później, nie będzie musiał czytać kodu, aby dowiedzieć się, czy
i
lubj
jest zmienną, czy jednostką urojoną). - jest szybszy (źródło: Mathworks).
Zauważ, że pełna składnia 1i
jest poprawna z dowolną liczbą poprzedzającą symbol:
>> a = 3 + 7.8j
a =
3.0000 + 7.8000i
Jest to jedyna funkcja, którą można trzymać z liczbą bez operatora między nimi.
Pułapki
Chociaż ich użycie jako fikcyjnej zmiennej jednostkowej OR jest całkowicie legalne, oto tylko mały przykład tego, jak mylące może się stać, jeśli oba sposoby zmienią się:
Zastąpmy i
i uczyńmy z niego zmienną:
>> i=3
i =
3
Teraz i
jest zmienną (posiadającą wartość 3
), ale zastępujemy jedynie skrót stenograficzny jednostki urojonej, pełna forma jest nadal poprawnie interpretowana:
>> 3i
ans =
0.0000 + 3.0000i
Co pozwala nam teraz budować najbardziej niejasne formuły. Pozwalam ci ocenić czytelność wszystkich następujących konstrukcji:
>> [ 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
Jak widać, każda wartość w powyższej tablicy zwraca inny wynik. Chociaż każdy wynik jest prawidłowy (pod warunkiem, że taka była pierwotna intencja), większość z was przyzna, że odczytanie kodu pełnego takich konstrukcji byłoby koszmarem.
Używanie „length” dla tablic wielowymiarowych
Częstym błędem koderów MATLAB jest używanie funkcji length
macierzy (w przeciwieństwie do wektorów , dla których jest przeznaczona). Funkcja length
, jak wspomniano w jej dokumentacji , „ zwraca długość największego wymiaru tablicy ” danych wejściowych.
W przypadku wektorów zwracana wartość length
ma dwa różne znaczenia:
- Łączna liczba elementów w wektorze.
- Największy wymiar wektora.
W przeciwieństwie do wektorów powyższe wartości nie byłyby równe dla tablic o więcej niż jednym wymiarze nie singletonowym (tj. O rozmiarze większym niż 1
). Dlatego użycie length
macierzy jest niejednoznaczne. Zamiast tego zaleca się korzystanie z jednej z poniższych funkcji, nawet podczas pracy z wektorami, aby wyjaśnić intencję kodu:
-
size(A)
- zwraca wektor wiersza, którego elementy zawierają liczbę elementów wzdłuż odpowiedniego wymiaruA
-
numel(A)
- zwraca liczbę elementów wA
Odpowiednikprod(size(A))
. -
ndims(A)
- zwraca liczbę wymiarów w tablicyA
Odpowiedniknumel(size(A))
.
Jest to szczególnie ważne, gdy pisze się „zorientowane na przyszłość” wektoryzowane funkcje biblioteczne, których dane wejściowe nie są wcześniej znane i mogą mieć różne rozmiary i kształty.