Vi skall nu se, hur man kan ber¨akna numeriska derivator. Antag att vi vill ber¨akna derivatan av f (x) i en punkt x = a, och att dess Taylor–utveckling kring denna punkt ¨ar
f (a + h) = f (a) + f0(a)h + f00(θ)
2 h2, θ ∈ [a, a + h].
Uttrycket Dh = f (a+h)−f (a)
h kommer d¨arf¨or ge allt noggrannare approximationer f¨or derivatan d˚a h minskar, eftersom Dh = f0(a) + f00(θ)h/2. H¨ar ¨ar ett vektoriserat program med vilket man kan studera felet d˚a man till¨ampar formeln p˚a f (x) = sin x f¨or olika h-v¨arden (\n anger ny rad):
a = 1; h = logspace(-1,-16,16);
Dh = (sin(a+h) - sin(a))./h;
fel = abs(Dh - cos(a)); tab = [h;fel];
disp(’ h fel’),fprintf(’ %8.1e %18.15f \n’,tab)
Resultaten lagrades i en matris tab, beh¨andigt utskriven en kolumn per rad med kommandot fprintf :
h fel
1.0e-01 0.042938553332751 1.0e-02 0.004216324856271 1.0e-03 0.000420825507813 1.0e-04 0.000042074449519 1.0e-05 0.000004207362275 1.0e-06 0.000000420746809 1.0e-07 0.000000041827691 1.0e-08 0.000000002969885 1.0e-09 0.000000052541266 1.0e-10 0.000000058481036 1.0e-11 0.000001168704061 1.0e-12 0.000043240216924 1.0e-13 0.000733915900314 1.0e-14 0.003706976198187 1.0e-15 0.014809206444439 1.0e-16 0.540302305868140
Kommandot fprintf kan ocks˚a anv¨andas f¨or att skriva data till en fil (se help fprintf). Vi ser att felet f¨orst minskar, men sedan igen b¨orjar ¨oka.
Varje fel i t¨aljaren multipliceras med en faktor 1/h, s˚a att vi ist¨allet f¨or det matematiska felet |Dh − f0(a)| ≤ h2|f00(θ)| i verkligheten f˚ar felet
|Dh − f0(a)| ≈ h
2|f00(θ)| + 2eps h , d¨ar eps ¨ar maskinprecisionen. H¨ogra membrum minimeras, om h = 2p
eps/|f00(θ)|.
Vi kan nu konstruera en ny rutin f¨or ber¨akning av derivator. Om andra derivatan ¨ar uppifr˚an begr¨ansad:
|f00(x)| ≤ M2, s˚a g¨aller f¨oljande olikhet f¨or det matematiska felet: |Dh − f0(a)| ≤ M22 h. Om det absoluta felet vid en funktionsber¨akning ¨ar mindre ¨an δ, s˚a kan det totala felet vid den numeriska ber¨akningen av funktionsderivatan approximeras med
fel(D(h)) = M2h
2 + 2δ h .
Detta fel minimeras om h = hmin = 2pδ/M2, vilket ger uttrycket fel(D(hmin)) = M2pδ/M2+
√ δ
δ/M2 = 2√
δM2. Vi kan d˚a modifiera programmet p˚a f¨oljande s¨att:
function d = deriv(fname,a,delta,M2);
%
% Invariabler:
% fname en str¨ang som inneh˚aller funktionens namn.
% a: det v¨arde av x f¨or vilket f’(x) ber¨aknas.
% delta: absoluta felet vid funktionsber¨akningen.
% M2: en uppskattning av andra derivatans storlek n¨ara a.
%
% Utvariabler:
% d: en approximation f¨or f’(a).
% err: en uppskattning av felet i d.
%
hopt = 2*sqrt(delta/M2);
d = (feval(fname,a+hopt) - feval(fname,a))/hopt;
H¨ar har anv¨ants funktionen feval, vars f¨orsta argument ¨ar en str¨ang, som inneh˚aller funktionsnamnet, och de ¨ovriga argumenten ¨ar funktionens egna argument.
Programmet f¨oruts¨atter att man kan uppskatta det absoluta felet δ och andra derivatans ¨ovre gr¨ans M2, men man kan anv¨anda konstanta v¨arden av dessa parametrar f¨or att underl¨atta programmets anv¨andning.
5.4. Interpolation
D˚a vi vill approximera data, utg˚ar vi fr˚an ett antal punkter (x1, y1), (x2, y2), . . ., (xn, yn) och f¨ors¨oker konstruera en funktion f (x), som beskriver punkterna s˚a bra som m¨ojligt. Typen av funktion best¨ams av punkterna. Om de t.ex. oscillerar, s˚a ¨ar det l¨ampligt att anv¨anda sig av trigonometriska funktioner f¨or att approximera dem. I m˚anga fall kan ett polynom av l˚agt gradtal vara l¨ampligt. Minsta kvadratmetoden, som vi redan anv¨ant, kan anv¨andas om man har flere datapunkter ¨an obekanta parametrar i funktionen.
Det finns en speciell typ av approximationsproblem d¨ar funktionen passerar genom datapunkterna. Detta inneb¨ar, att f (xi) = yi, i = 1 : n. Vi s¨ager i detta fall att f interpolerar data. Om approximations- funktionen ¨ar ett polynom kan vi uttrycka interpolationsproblemet p˚a f¨oljande s¨att:
D˚a x1, x2, . . . , xn och y1, y2, . . . , yn ¨ar givna, s¨ok ett polynom pn−1(x) av gradtalet n − 1 (eller l¨agre) som uppfyller villkoret pn−1(xi) = yi f¨or alla i = 1 : n.
S˚alunda interpolerar t.ex. polynomet p2(x) = 1 + 4x − 2x2 punkterna (−2, −15), (3, −5) och (1, 3) (se figuren).
Varje talpar (xi, yi) kan uppfattas som en punkt p˚a en kurva, beskriven av n˚agon funktion g(x) : yi = g(xi). Funktionen g kan vara explicit definierad, t. ex. om vi vill approximera sin x i punkterna x = 0, π/2 och π med ett andragradspolynom. Men funktionen kan ocks˚a vara implicit definierad, om vi t.ex. vill interpolera m¨atdata.
Hur uttrycks interpolanten pn−1(x)? Ist¨allet f¨or att anv¨anda de ”naturliga” baspolynomen 1, x och x2, skulle vi kunna anv¨anda den alternativa basen 1, (x + 2) och (x + 2)(x − 3).
I denna bas kan det tidigare n¨amnda interpolationspolynomet p2(x) uttryckas p2(x) = −15 + 2(x + 2) − 2(x + 2)(x − 3).
Olika baser har olika f¨ordelar.
N¨ar vi har best¨amt oss f¨or ett s¨att att representera interpolanten, hur ber¨aknar vi d¨arp˚a koefficienterna?
Det visar sig att detta problem leder till l¨osningen av ett ekvationssystem med en koefficientmatris av en best¨amd symmetri.
Sedan koefficienterna blivit ber¨aknade, hur kan vi p˚a ett effektivt s¨att ber¨akna interpolanten? Detta problem klarnar n¨ar vi ritat en graf av polynomet.
Den klassiska metoden att ber¨akna ett interpolationspolynom har uppkallats efter Alexandre-Th´eophile Vandermonde (1735-1796, fransk matematiker, som bl.a. studerade determinanter). Som ett exempel skall vi studera problemet att finna det tredjegradspolynom
p3(x) = a1 + a2x + a3x2 + a4x3 som interpolerar punkterna (−2, 10), (−1, 4), (1, 6) och (2, 3).
Varje interpolationspunkt ger d˚a upphov till en line¨ar ekvation med fyra obekanta:
a1 − 2a2 + 4a3 − 8a4 = 10 a1 − a2 + a3 − a4 = 4 a1 + a2 + a3 + a4 = 6
a1 + 2a2 + 4a3 + 8a4 = 3 (1)
Vi kan uttrycka detta ekvationssystem i matrisform:
1 −2 4 −8
1 −1 1 −1
1 1 1 1
1 2 4 8
a1 a2 a3 a4
=
10
4 6 3
L¨osningen a=[4.5000 1.9167 0.5000 -0.9167]’ till dessa fyra ekvationer f˚ar man med f¨oljande enkla MATLAB-program:
y = [10; 4; 6; 3];
V = [1 -2 4 -8; 1 -1 1 -1; 1 1 1 1; 1 2 4 8];
a = V\y;
Vi skall nu studera det n–dimensionella interpolationsproblemet. I detta fall skall vi best¨amma koefficien- terna a1, a2, . . . , an f¨or polynomet
pn−1(x) = a1 + a2x + a3x2 + · · · + anxn−1 s˚a att
pn−1(xi) = a1 + a2xi + a3x2i + · · · + anxn−1i = yi f¨or alla i = 1 : n. Genom att skriva ekvationerna i matrisform f˚ar vi
1 x1 x21 · · · xn−11 1 x2 x22 · · · xn−12 1 x3 x23 · · · xn−13
... ... ... . . . ...
1 xn x2n · · · xn−1n
a1 a2 a3 ...
an
=
y1 y2 y3 ...
yn
Koefficientmatrisen (Vandermondes matris) kan vi kalla V . F¨or att vi skall kunna l¨osa interpolationsprob- lemet, m˚aste V vara icke-singul¨ar. Antag nu, att det finns en s˚adan vektor c, att V c = 0. Detta betyder, att polynomet
q(x) = c1 + c2x + · · · + cnxn−1
skulle f¨orsvinna i var och en av de (disjunkta) punkterna x = x1, x2, . . . , xn, m.a.o. q(x) ¨ar ett polynom av gradtalet n − 1 som har n skilda r¨otter. Detta kan endast intr¨affa om polynomet ¨ar ett noll–polynom (dvs c = 0). Allts˚a kan V inte vara en singul¨ar matris.
Vi skall nu beskriva n˚agra s¨att att konstruera matrisen V . Eftersom den i:te raden av V inneh˚aller potenser av xi, och exponenterna v¨axer fr˚an 0 till n − 1 d˚a man g˚ar fr˚an v¨anster till h¨oger, s˚a kan man konstruera matriselementen med en vanlig dubbelslinga:
n = length(x); V = zeros(n,n);
for i = 1:n
% i:te raden:
for j = 1:n
V(i,j) = x(i)^(j-1);
end end
Detta ¨ar en radorienterad algoritm, eftersom den verkar p˚a matrisen rad f¨or rad.
Den inre slingan i denna skript kan vektoriseras med hj¨alp av elementvis exponentiering. S˚aledes ger t.ex.
MATLAB-kommandot u = [1 2 3 4].^[3 5 2 3] ˚at radvektorn u v¨ardet [1 32 9 64].
F¨or att r¨akna ut elementen i den i:te raden av V m˚aste man upph¨oja skal¨aren xi i var och en av exponen- terna i radvektorn 0 : n − 1 = (0, 1, . . . , n − 1). Kommandot r = (x(i)*ones(1,n)).^(0:n-1) kommer d¨arf¨or att tillordna vektorn (1, xi, x2i, . . . , xn−1i ) till r. Den i:te raden i V kan anges med V(i,:), och vi f˚ar d˚a skripten
n = length(x); V = zeros(n,n);
for i=1:n
% i:te raden i V:
V(i,:) = (x(i)*ones(1,n)).^(0:n-1);
end
Vi kan ocks˚a kasta om slingorna i den ursprungliga skripten, varigenom vi f˚ar en kolumnorienterad algoritm:
n = length(x); V = zeros(n,n);
for j=1:n
% j:te kolumnen:
for i = 1:n
V(i,j) = x(i)^(j-1);
end end
Om j > 1, s˚a kan V (i, j) uttryckas som produkten av x(i) och V (i, j − 1), vilket visar att potenseringarna kan g¨oras genom successiva multiplikationer:
n = length(x); V = zeros(n,n);
V = ones(n,n);
for j=2:n
% j:te kolumnen:
for i = 1:n
V(i,j) = x(i)*V(i,j-1);
end end
Den j:te kolumnen bildas allts˚a genom elementvis vektormultiplikation:
x1
...
xn
. ∗
V1,j−1 ...
Vn,j−1
=
V1,j
...
Vn,j
som kan utf¨oras med MATLAB–kommandot V(:,j) = x.*V(:,j-1). Vi kommer till sist fram till f¨oljande MATLAB-funktion f¨or interpolering enligt Vandermondes metod:
function a = interpv(x,y)
%
% Invariabler:
% x: en kolumnvektor med n (olika) element
% y: en kolumnvektor med n element
%
% Utvariabel:
% a: en kolumnvektor med n element f¨or vilka g¨aller att om
% p(x) = a(1) + a(2)x + ... + a(n)x^(n-1) s˚a ¨ar
% p(x(i)) = y(i) , i = 1:n
%
n = length(x);
V = ones(n,n);
for j = 2:n
% j:te kolumnen:
V(:,j) = x.*V(:,j-1);
end
a = V\y;
Vi skall nu beskriva en effektiv metod f¨or att ber¨akna polynomv¨ardena pn−1(x) = a1 + . . . + anxn−1 f¨or x = z, d˚a vi k¨anner z och a(1:n). Vi kan ber¨akna v¨ardet av pn−1(z) direkt genom att summera potenser av x:
n = length(a);
zk = 1;
pz = a(1);
for k = 2:n zk = z*zk;
pz = pz + a(k)*zk;
end
men det finns en effektivare metod. Vi skall f¨or enkelhetens skull till¨ampa den p˚a ett tredje gradens poly- nom, som vi skriver i formen p3(x) = a1 + a2x + a3x2 + a4x3 = ((a4x + a3)x + a2)x + a1. Polynomets v¨arde i z kan f¨oljaktligen ber¨aknas med programfragmentet
pz = a(4);
pz = z*pz + a(3);
pz = z*pz + a(2);
pz = z*pz + a(1);
F¨or ett godtyckligt gradtal kan man uttrycka denna kedjeregel med kommandosekvensen n = length(a);
pz = a(n);
for i=n-1:-1:1
pz = z*pz + a(i);
end
Denna metod, som kallas Horners regel ¨ar uppkallad efter William George Horner, en engelsk matematiker som beskrivit den 18191.
L˚at oss anta, att vi vill ber¨akna interpolanten i m˚anga, skilda punkter. Vi skall anta att vektorn z(1:m) har blivit initialiserad, och att vi vill tillordna v¨ardet pn−1(z(i)) till pz(i) f¨or alla i = 1 : m. Detta kan naturligtvis g¨oras genom att man upprepar Horners metod i varje punkt:
1W.G. Horner,”A new method of solving numerical equations of all orders, by continuous approximation,”Phil. Trans., Vol. 109, 1819, ss. 308-335
m = length(z);
n = length(a);
pz = zeros(m,1);
for j = 1:m
% Ber¨akna p(z(j)).
pz(j) = a(n);
for i=n-1:-1:1
pz(j) = z(j)*pz(j) + a(i);
end end
Vi kan vektorisera detta programfragment genom att t¨anka p˚a vad det inneb¨ar att man ”samtidigt”ber¨aknar interpolanterna i varje punkt zi. Antag, att m = 5 och n = 4 (dvs vi vill ber¨akna en kubisk interpolant i fem punkter). Det f¨orsta steget i Horners metod kan d˚a uttryckas
pz(1) pz(2) pz(3) pz(4)
=
a(4) a(4) a(4) a(4)
I vektorform kan detta skrivas pz = a(n)*ones(m,1). N¨asta steg kan g¨oras simultant p˚a analogt s¨att:
pz(1) pz(2) pz(3) pz(4)
=
z(1) ∗ pz(1) z(2) ∗ pz(2) z(3) ∗ pz(3) z(4) ∗ pz(4)
+
a(3) a(3) a(3) a(3)
eller i vektorform pz = z.*pz + a(3). F¨or en kubisk interpolant f˚ar vi allts˚a f¨oljande MATLAB-skript:
pz = a(4)*ones(m,1) pz = z.*pz + a(3);
pz = z.*pz + a(2);
pz = z.*pz + a(1);
Detta programfragment kan vi generalisera till f¨oljande MATLAB-rutin f¨or att ber¨akna polynomv¨arden av vektorargument med Horners metod:
function pz = hornerv(a,z)
%
% Invariabler:
% a: en kolumnvektor med n element
% z: en kolumnvektor med m element
%
% Utvariabel:
% pz: en kolumnvektor med n element, f¨or vilka g¨aller att
% om p(x) = a(1) + ... + a(n)x^(n-1) , s˚a ¨ar
% pz(i) = p(z(i)) d˚a i=1:m.
%
n = length(a);
m = length(z);
pz = a(n)*ones(m,1);
for k = n-1:-1:1
pz = z.*pz + a(k);
end
Varje uppdatering av pz kr¨aver 2m flyttalsoperationer, s˚a att 2mn operationer beh¨ovs totalt.
Som en till¨ampning skall vi studera ett program, som ritar kubiska interpolanter av sin x inom intervallet [0, 2π]. Punkternas x–koordinater v¨aljs slumpm¨assigt med rand–funktionen, och sorteras i storleksordning med sort. Sinuskurvan anges med en heldragen linje, och interpolanten med en streckad linje.
% programfil: intsin
% Programmet ritar fyra slumpartade kubiska interpolanter f¨or
% sin(x) inom intervallet [0,2pi] och
% anv¨ander Vandermondes metod.
close
x1 = linspace(0,2*pi,100)’;
y1 = sin(x1);
for k=1:4
x = 2*pi*sort(rand(4,1));
y = sin(x);
a = interpv(x,y);
pz = hornerv(a,x1);
subplot(2,2,k)
plot(x1,y1,’-’,x1,pz,’--’,x,y,’o’) axis([0 2*pi -2 2])
end
Nedanst˚aende figur visar ett exempel p˚a grafiken, och visar ocks˚a hur valet av punkter p˚averkar ¨overensst¨am- melsen mellan den ursprungliga kurvan och interpolanten.