BYFE/EMFE 1000, 2012/2013 Numerikkoppgaver uke 37 og 38 Oppgave 1 Funksjoner og tangenter 2.1: 15 a) f(x) = x 2 f(2) = 2 2 = 4 f (x) = 2x f (2) = 2 2 = 4 Likninga for tangenten kan vi nne ved formelen y y 0 = a(x x 0 ), der a er stigningsallet til linja og (x 0, y 0 ) er et punkt på linja. Vi får: y 4 = 4(x 2) y = 4x 4. Grafen til f og tangenten i (2, 4) er tegna i gur 1. Dem er laga på denne måten i Octave: octave-3.2.4.exe:8> x=-3:.1:3; octave-3.2.4.exe:9> y=x.^2; octave-3.2.4.exe:10> tang=4*x-4; octave-3.2.4.exe:11> plot(x,y) octave-3.2.4.exe:12> hold on octave-3.2.4.exe:13> plot(x,tang,'r') octave-3.2.4.exe:14> hold off octave-3.2.4.exe:15> axis([-2 3-3 10]) 2.1: 15 b) Likning for tangent: f(x) = 1 + x 2 f(2) = 1 + 2 2 = 5 f (x) = 1 2 1 + x (1 + 2 x2 ) = f (2) = 2 = 2 1 + 2 2 5 x 1 + x 2 y 5 = 2 5 (x 2) y = 2 5 x + 1 5 1
Figur 1: Plott for oppg. 2.1: 1 a). I Octave vel vi å plotte for x [ 2, 3]: octave-3.2.4.exe:27> x=-2:.1:5; octave-3.2.4.exe:28> y=sqrt(1+x.^2); octave-3.2.4.exe:29> tang=2/sqrt(5)*x+1/sqrt(5); octave-3.2.4.exe:30> plot(x,y) octave-3.2.4.exe:31> hold on octave-3.2.4.exe:32> plot(x,tang,'r') octave-3.2.4.exe:33> hold off Grafen til f og tangenten er vist i gur 2 2.1: 15 c) f(x) = ln x f(2) = ln 2 f (x) = 1 x f (2) = 1 2 Likning for tangenten: y ln 2 = 1/2 (x 2) y = x/2 1 + ln 2. Vi plotter: octave-3.2.4.exe:35> x=.1:1e-2:4; octave-3.2.4.exe:36> y=log(x); octave-3.2.4.exe:37> tang=.5*x-1+log(2); octave-3.2.4.exe:38> plot(x,y) 2
Figur 2: Plott for oppg. 2.1: 1 b) octave-3.2.4.exe:39> hold off octave-3.2.4.exe:40> plot(x,y) octave-3.2.4.exe:41> hold on octave-3.2.4.exe:42> plot(x,tang,'r') octave-3.2.4.exe:43> hold off Resultatet er vist i gur 3 Figur 3: Plott for oppg. 2.1: 1 c) 3
2.1: 15 d) f(x) = e x/2 f(2) = e 2/2 = e ( x ) f (x) = e x/2 1 = 2 2 ex/2 f (2) = e 2 Tangent: y e = e/2 (x 2) y = e/2 x. Plottet er vist i gur 4 og laget slik: octave-3.2.4.exe:47> x=-2:.1:4; octave-3.2.4.exe:48> y=exp(x/2); octave-3.2.4.exe:49> tang=e/2*x; octave-3.2.4.exe:50> plot(x,y) octave-3.2.4.exe:51> hold on octave-3.2.4.exe:52> plot(x,tang,'r') octave-3.2.4.exe:53> hold off Figur 4: Plott for oppg. 2.1: 1 d) Oppgave 2 Numerisk derivasjon a) Jeg har valgt med denne funksjonen: f(x) = sin x 2. 4
b) f (x) = cos x 2 (x 2 ) = 2x cos x 2. Jeg velger a = 1 og får at f (a) = f (1) = 2 cos 1. c) Det vil være nyttig å lage ei funksjonsl for funksjonen vår: function F=FunkTilOppg2(x) % Funksjonen f(x) = sin x^2. Funksjonen tar vektor-argument F=sin(x.^2); Jeg har valgt å kalle denne FunkTilOppg2.m. Vi regner ut gjennomsnittlig vekstrate for noen verdier av h: octave-3.2.4.exe:57> clear all octave-3.2.4.exe:58> h=1; octave-3.2.4.exe:59> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = -1.5983 octave-3.2.4.exe:60> h=.5; octave-3.2.4.exe:61> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = -0.12680 octave-3.2.4.exe:62> h=.1; octave-3.2.4.exe:63> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 0.94145 octave-3.2.4.exe:64> h=.05; octave-3.2.4.exe:65> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0174 octave-3.2.4.exe:66> h=1e-2; octave-3.2.4.exe:67> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0689 octave-3.2.4.exe:68> h=1e-3; octave-3.2.4.exe:69> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0795 octave-3.2.4.exe:70> h=1e-4; octave-3.2.4.exe:71> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0805 I følge Octave er f (1) = 2 cos 1 1.0806, så vi begynner å nære oss. d) Vi gjentar det vi nettop gjore med bakover-formelen: octave-3.2.4.exe:75> h=1; octave-3.2.4.exe:76> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 0.84147 octave-3.2.4.exe:77> h=.5; octave-3.2.4.exe:78> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h 5
Rate = 1.1881 octave-3.2.4.exe:79> h=.1; octave-3.2.4.exe:80> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 1.1718 octave-3.2.4.exe:81> h=.05; octave-3.2.4.exe:82> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 1.1318 octave-3.2.4.exe:83> h=1e-2; octave-3.2.4.exe:84> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 1.0918 octave-3.2.4.exe:85> h=1e-3; octave-3.2.4.exe:86> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 1.0817 octave-3.2.4.exe:87> h=1e-4; octave-3.2.4.exe:88> Rate=(FunkTilOppg2(1)-FunkTilOppg2(1-h))/h Rate = 1.0807 e) Gjennomsnittet blir ( 1 f(a + h) f(a) + 2 h f(a + h) f(a h) 2h Altså: f (a) ) f(a) f(a h) f(a + h) f(a) + f(a) f(a h) = = h 2h f(a + h) f(a h) 2h når h er passe liten. (Vi skal ikke problematisere hva vi mener med passe liten her.) Legg merke til at dette f (a)-estimatet er helt uavhengig av f(a). f) Vi gjentar prosedyren fra c) og d) med denne nye formelen: octave-3.2.4.exe:90> h=1; octave-3.2.4.exe:91> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = -0.37840 octave-3.2.4.exe:92> h=.5; octave-3.2.4.exe:93> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 0.53067 octave-3.2.4.exe:94> h=.1; octave-3.2.4.exe:95> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 1.0566 octave-3.2.4.exe:96> h=.05; octave-3.2.4.exe:97> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 1.0746 octave-3.2.4.exe:98> h=1e-2; octave-3.2.4.exe:99> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 1.0804 6
octave-3.2.4.exe:100> h=1e-3; octave-3.2.4.exe:101> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 1.0806 octave-3.2.4.exe:102> h=1e-4; octave-3.2.4.exe:103> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1-h))/2/h Rate = 1.0806 Det ser ut til at vi nærmer oss riktig verdi for f (a) raskere på denne måten; for h = 10 3 ser vi faktisk ikke forskjell med det antallet desimaler som blir skrevet til skjerm. (Octave opererer med langt ere desimaler egentlig; om du vil ha ere desimaler skrevet til skjerm, kan du skrive 'format long'.) g) Vi kan lage en h-vektor som blir mindre og mindre ved å starte på 1 og så dele på to igjen og igjen. Dette kan vi gjøre slik i Octave: octave-3.2.4.exe:4> n=0:5; octave-3.2.4.exe:5> hvekt=.5.^n hvekt = 1.000000 0.500000 0.250000 0.125000 0.062500 0.031250 Vi lager vektorer som beregner f (a) ut fra de tre metodene over: DerivFram=(FunkTilOppg2(1+hVekt)-FunkTilOppg2(1))./hVekt; DerivBak=(FunkTilOppg2(1)-FunkTilOppg2(1-hVekt))./hVekt; DerivMidt=(FunkTilOppg2(1+hVekt)-FunkTilOppg2(1-hVekt))./(2*hVekt); Vi plotter feilen i estimatet ved hjelp av semilogx-kommandoen: octave-3.2.4.exe:79> DerivFasit=2*cos(1) DerivFasit = 1.0806 octave-3.2.4.exe:80> semilogx(hvekt,derivfram-derivfasit,'b') octave-3.2.4.exe:81> hold on octave-3.2.4.exe:82> semilogx(hvekt,derivbak-derivfasit,'r') octave-3.2.4.exe:83> semilogx(hvekt,derivmidt-derivfasit,'g') octave-3.2.4.exe:84> hold off octave-3.2.4.exe:85> legend('forover-formel','bakover-formel','midtpunktsformel') octave-3.2.4.exe:86> axis([.02 1.5-3.5]) octave-3.2.4.exe:87> print -dpng DerivKonvergens.png Langs y-aksen har vi her dieransen mellom derivasjons-estimatet og den riktige verdien for den deriverte. Vi ser i gur 5 at alle tre metodene gir et estimat med en feil som ser ut til å gå mot 0 når h blir mindre og mindre. Men plottet for midtpunktsformelen ser ut til å gå mot null raskest. (Her er det nok enklest å lese plottet fra høgre mot venstre.) 7
Figur 5: Plott som viser feilen i ulike estimat for f (a) som funksjon av h. Plottet er semi-logaritmisk. Den blå kurva tilsvarer forover-formelen, den røde tilsvarer bakover-formelen og den grønne er midtpunktsformelen. Se tekst for detaljer. h) Maskinpresisjonen nner vi slik: octave-3.2.4.exe:31> eps ans = 2.2204e-016 Dette er jo et veldig lite tall, men det er ikke null. Vi velger noen veldig små verdier for h og bergener den deriverte med forover-formelen: octave-3.2.4.exe:60> DerivFasit=2*cos(1) DerivFasit = 1.0806 octave-3.2.4.exe:61> h=1e-13; octave-3.2.4.exe:62> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0802 octave-3.2.4.exe:63> h=1e-14; 8
octave-3.2.4.exe:64> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.0769 octave-3.2.4.exe:65> h=1e-15; octave-3.2.4.exe:66> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 1.2212 octave-3.2.4.exe:67> h=5e-16; octave-3.2.4.exe:68> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 0.88818 octave-3.2.4.exe:69> h=1e-16 h = 1.0000e-016 octave-3.2.4.exe:70> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 0 octave-3.2.4.exe:71> h=5e-17; octave-3.2.4.exe:72> Rate=(FunkTilOppg2(1+h)-FunkTilOppg2(1))/h Rate = 0 Nå ser vi faktisk at jo mindre h blir, jo dårligere estimat får vi for f (a). Her ser vi en vesens-forskjell mellom numeriske metoder og analytisk matematikk; matematisk skal (f(x+h) f(x))/h f (a) vilkårsløst nærme seg 0 når h nærmer seg 0 (dersom f er deriverbar i x = a), mens numerisk sett, blir den deriverte best estimert med en liten - men endeleig - h. Dette skyldes at datamaskiner har en nedre grense for hvor små tall den kan skille fra hverandre. I gur 6 har vi plotta feilen i de tre ulike måtene å estimere f (1) på for et veldig stort område av h-verdier. Her er både x- og y-aksen logaritmiske. Vi ser at det alle beste estimatet får vi med midtpunktsformelen for h 10 6. Oppgave 3 Den deriverte fra en tabell Her tar vi utgangspunkt i oppg. 2.1: 15 i læreboka. a) Plottet kan lages slik: octave-3.2.4.exe:121> Aar=1900:10:2000; octave-3.2.4.exe:121> Bef=[1650 1750 1860 2070 2300 2520 3020 3700 4450 5300 6123]; octave-3.2.4.exe:123> plot(aar,bef) octave-3.2.4.exe:124> xlabel('aar') octave-3.2.4.exe:125> ylabel('befolkning') og resultatet kan sees i gur 7. b) Vi lar B(t) være antall millioner mennesker i verden i år t. Om vi bruker formelen fra 2 c) kan vi for eksempel estimere B(1910) slik B (1910) B(1920) B(1900) 1920 10910 9 = B(1910 + 10) B(1910 10) 2 10.
Figur 6: Feilen i de ulike estimatene for f (a) for h-verdier fra 1 ned mot 10 18. 10
Figur 7: Verdens befolkning i antall millioner som funksjon av årstall. I Octave får vi: octave-3.2.4.exe:128> (Bef(3)-Bef(1))/(Aar(3)-Aar(1)) ans = 10.500 Altså, i år 1910 vokste jordas befolkning med ca 10.5 millioner mennesker per år. For de andre årene får vi B (1920) 16, B (1930) 22, B (1940) 22.5, B (1950) 36, B (1960) 59, B (1970) 71.5, B (1980) 80 og B (1990) 83.65. c) Siden vi ikke har B(1890), kan vi ikke bruke midpunktsformelen for å estimere B (1900). På samme måte er vi ute at stand til bruke midpunktsformelen for å nne B (2000) siden vi ikke har fått oppgitt B(2010). Derimot kan vi bruke forover- og bakover-formlene: B (1900) B (2000) B(1910) B(1900) 1910 1900 B(2000) B(1990) 2000 1990 = 10 = 82.3 d) Alle de estimatene vi har regna ut her, kan gjøres i ett jafs med dette skriptet: % Vektor med årstall: 11
Aar=1900:10:2000; % Vektor med befolkning: Bef=[1650 1750 1860 2070 2300 2520 3020 3700 4450 5300 6123]; % Bestemmer lengda av Aar og tilordner dette tallet til N: N=length(Aar); for n=1:n if n==1 % For det første punktet Bderiv(n)=(Bef(n+1)-Bef(n))/(Aar(n+1)-Aar(n)); % Forover-formel elseif n==n % For det siste punktet Bderiv(n)=(Bef(n)-Bef(n-1))/(Aar(n)-Aar(n-1)); % Bakover-formel else % For alle andre punkt Bderiv(n)=(Bef(n+1)-Bef(n-1))/(Aar(n+1)-Aar(n-1)); % Midtpunktsformel end end % Skriver estimatene for de deriverte til skjerm: Bderiv Jeg har kalt skriptet BefDeriv.m. Vi kjører det i Octave: octave-3.2.4.exe:150> BefDeriv Bderiv = Columns 1 through 8: 10.000 10.500 16.000 22.000 22.500 36.000 59.000 71.500 Columns 9 through 11: 80.000 83.650 82.300 d) Plottet vi får opp når vi skriver plot(aar,bderiv) i Octave, er vist i gur 8. e) Den prosentvise veksten, altså vekst i forhold til foketall, er gitt ved B (t)/b(t) 100%. Dette kan plottes i Octave slik: plot(aar,bderiv./bef*100). Resultatet er vist i gur 9. Vi ser at tilveksten har variert fra 0.6% til opp mot 2% gjennom det forrige århundret. Heldigvis er også den prosentvise tilveksten avtakende mot slutten. 12
Figur 8: Tilnærma årlig tilvekst i verdens befolkning som funksjon av årstall. Figur 9: Tilnærma årlig prosentvis tilvekst i verdens befolkning som funksjon av årstall. 13