2013-05-29 13 views

Odpowiedz

6

Tak, możesz.

Jest ładny submission on the file exchange, który pozwala dokładnie to zrobić. Działa poprzez przybliżenie krzywej przez wielomian Czebyszowa, a następnie znalezienie wszystkich prawdziwych korzeni tego wielomianu.

Jeśli chcesz, możesz użyć tych oszacowań dla pierwiastków jako wartości początkowych dla fzero, ale często (przynajmniej dla gładkich i innych dobrze zachowujących się krzywych) wymagania dokładności mogą być już spełnione przy użyciu aproksymacji Chebychev wyższego rzędu .

Dla przykładu, przy użyciu tylko 18 ocen funkcyjnych (mam nieco zmodyfikowaną wersję pliku, ale istota jest taka sama):

>> f = @(A) 17.7*sin(A).*cos(A)+87*sin(A).^2-9.65*cos(A)-47*sin(A); 
>> R = FindRealRoots(f, -5,5, 17) 
R = 
    -3.709993256346244 
    -3.345207732130925 
    -0.201929737187637 
    0.572382702285053 
    2.573423209113534 
    2.937157987217741 

>> R2 = R; 
>> funcCount = 0; 
>> for ii = 1:numel(R) 
     [R2(ii), ~,~, output] = fzero(f,R2(ii)); 
     funcCount = funcCount + output.funcCount; 
    end 
>> max(abs(R2(:)-R(:))) 
ans = 
    8.564253235401331e-004 
>> funcCount 
ans = 
    46 

przykład, jest tylko 8 części na dziesięć tysięcy poprawy za nie mniej niż 46 dodatkowych ocen funkcji.

+0

@RobertP .: Brak tego co wiem ... co jest nieco dziwne, ponieważ [wielomiany Chebychev] (http://en.wikipedia.org/wiki/Chebyshev_polynomials) są najlepszym wyborem dla przybliżeń wielomianowych. Rzeczywiście, przynajmniej ze względu na typ funkcji, z którą masz do czynienia (płynne, ciągłe itd.), Dokładność może być dość wysoka. Jedyną wadą jest to, że może być trudno wybrać "dobre" wartości 'n' (w tym miejscu przydatna jest wbudowana funkcja kreślenia). –

+1

+1 za sugestię wielomianów Czebyszewa, znalazłem je bardzo przydatne w wielu aspektach obliczeń. – bla

2

Najpierw jest Matlab wbudowanego w wariancie, który używa symbolicznego matematyki przybornik: mathworks.com/help/symbolic/mupad_ref/numeric-realroots.html

Inną opcją, jeśli funkcja jest dobrze wychowany, jest po prostu nakarmić fsolve z odpowiednimi domysły, więc mimo że jest za pomocą jest to wydajne obliczenie. Na przykład:

A=linspace(-5,5,1000); 
[email protected](A) 17.7.*sin(A).*cos(A)+87.*sin(A).^2-9.65*cos(A)-47*sin(A) 

idx = find(diff(sign(f(A)))); 
for n=1:numel(idx) 
    r(n)=fzero(f,A(idx(n))) 
end 

r= 
    -3.709541990613713 
    -3.345170894638306 
    -0.202018624930518 
    0.572128202319968 
    2.573643316565874 
    2.938014412541281 
+0

Dzięki @natan! Nie wiedziałem o 'numeric :: realroots'. Drugie rozwiązanie też było miłe! =) –

Powiązane problemy