2011-12-14 28 views
6

Jest jedna rzecz, której nie lubię na Matlabie: Czasami próbuje być zbyt inteligentny. Na przykład, jeśli mam negatywny pierwiastek kwadratowy jakWyłącz "inteligentne zachowanie" w Matlab

a = -1; sqrt(a) 

Matlab nie wygeneruje błąd, ale przełącza się w milczeniu na liczbach zespolonych. To samo dzieje się w przypadku logarytmów ujemnych. Może to prowadzić do trudnych do znalezienia błędów w bardziej skomplikowanym algorytmie.

Podobny problem jest Matlab „rozwiązuje” cicho niż kwadratowe układy liniowe, jak w poniższym przykładzie:

A=eye(3,2); b=ones(3,1); x = A \ b 

Oczywiście x nie spełnia A*x==b (rozwiązuje problemu zamiast najmniejszych kwadratów).

Czy istnieje możliwość wyłączenia tych "funkcji", a przynajmniej niech Matlab wydrukuje komunikat ostrzegawczy w takim przypadku? To bardzo by pomogło w wielu sytuacjach.

+1

Zastanawiam się, dlaczego ludzie popierają to pytanie. Myślę, że jest to całkowicie uzasadnione. Co więcej, jestem pewien, że jest wielu ludzi, którzy stracili czas na poszukiwanie subtelnych błędów z powodu opisanego zachowania. – Boris

+1

Sposób, w jaki twoje pytanie brzmi, może brzmieć jak "Naprawdę nie czytałem dokumentacji, która mówi, że Matlab obsługuje liczby zespolone, i to wyjaśnia, co robi operator odwrotnego ukośnika. Czy mogę zmusić Matlaba do zrobienia tego, co fałszywie zakładałem, że to zrobi, ponieważ jestem naprawdę sfrustrowany tym, że nie mogę odczytać dokumentacji? ". Chociaż nie zgadzam się z tobą w sprawie problemu z operatorem odwrotnego ukośnika, zgadzam się, że liczby zespolone mogą wskazywać na problem. Byłoby miło, gdyby w debugerze było "dbstop if complex" oprócz "dbstop if nan/inf". – Jonas

+0

@Jonas Próbowałem sformułować pytanie w taki sposób, aby czytelnik nie miał takiego wrażenia, wydaje mi się, że nie udało mi się :(Masz rację, dokumentacja jest na to doskonale jasna.Myślę, że Matlab "nadużywa" operatora, który może prowadzić do błędów, a to jest złe.Innym często popełnianym błędem przez początkujących jest: A (źle zdefiniowana) funkcja jak 'f = @ (x) x * ((x + 1)/x)' daje wynik 'f ([1,2]) = [1.6,3.2] 'podczas gdy większość początkujących oczekiwałaby wyniku" [2,3] ". W większym programie takie błędy są bardzo trudne do znalezienia. – Boris

Odpowiedz

3

Nie sądzę, że w waszych przykładach jest coś takiego jak "być mądrym". Pierwiastek kwadratowy liczby ujemnej jest złożony. Podobnie, operator lewego podziału jest zdefiniowany w Matlab jako obliczanie pseudo-odwrotności dla wejść innych niż kwadratowe.

Jeśli posiadasz aplikację, która nie powinna zwracać liczb zespolonych (uwaga na błędy zmiennoprzecinkowe!), Możesz użyć testu isreal, aby to przetestować. Jeśli nie chcesz, aby operator lewego podziału obliczył pseudoinwersję, sprawdź, czy A jest kwadratowy.

Alternatywnie, jeśli z jakiegoś powodu jesteś naprawdę w stanie zrobić walidacji wejścia, można przeciążać zarówno sqrt i \ tylko do pracy na liczbach dodatnich, a nie obliczać pseudoinverse.

+0

Oczywiście, mogę sprawdzić wszystkie moje parametry, ale w 90% przypadków, jeśli moje dane wejściowe są prawdziwe, dane wyjściowe powinny być również prawdziwe. Ponadto rozwiązanie systemu liniowego jest tym, czego ludzie w większości przypadków oczekują, gdy używany jest operator odwrotnego ukośnika. Po prostu chciałbym wywołać zachowanie za pomocą parametru. – Boris

+1

@Boris: Wygląda więc inaczej. W 100% przypadków, w których przyjmuję pierwiastek kwadratowy o wartości ujemnej, oczekuję złożonego wyniku. Ponadto używam operatora odwrotnego ukośnika wyłącznie w systemach, które są nadokreślone (ponieważ inne nie powinny nigdy występować w moich aplikacjach). – Jonas

+1

@Boris: Niestety nie ma wbudowanego przełącznika, który pozwala tylko na występowanie liczb rzeczywistych w obliczeniach (chyba że chcesz pracować ze wszystkimi liczbami całkowitymi). – Jonas

3

Musisz zrozumieć wszystkie konsekwencje tego, co piszesz i upewnić się, że używasz właściwych funkcji, jeśli masz zamiar zagwarantować dobry kod. Na przykład:

  • W pierwszym przypadku korzystania realsqrt zamiast
  • W drugim przypadku, należy inv(A) * b zamiast

lub alternatywnie zawierać odpowiednie kontrole przed/po wywołaniu wbudowany Funkcje. Jeśli chcesz to zrobić za każdym razem, zawsze możesz pisać swoje własne funkcje.

+0

* Ad hominem * nie został użyty (i został usunięty), ale poza tym rozwiązanie nie zasługuje na obniżenie. +1 ode mnie za znalezienie 'realsqrt'. – Jonas

+2

Propozycja 'inv (A) * b' jest bardzo powolna w wielu przypadkach (szczególnie gdy A jest rzadka) i nie powinna być używana. – Boris

+0

@Boris, zgadzam się, ale jeśli potrzebujesz wersji, która działa tylko wtedy, gdy A jest kwadratem i nie jest liczbą pojedynczą, to jest to najprostsza opcja. Najlepszym rozwiązaniem są dwa zawinięcia w ukośnik odwrotny w swojej własnej funkcji. – Nzbuu