4.3. Programmering i MATLAB MATLAB används ofta interaktivt, dvs ett kommando som man skriver, kommer genast att utföras, och resultatet visas. Men MATLAB kan också utföra kommandon som lagrats i filer, kallade M-filer. Vi har redan tidigare stött på M-filer som används för att lagra funktionsdefinitioner. En M-fil innehåller i allmänhet vanliga MATLAB-kommandon, och möjligen referenser till andra M-filer. Filer som innehåller MATLAB-kommandon kallas vanligen skriptfiler, och de kan alstras med ett vanligt editeringsprogram (t.ex. emacs) eller ordbehandlingsprogram. Också från kommandofönstret i MATLAB kan man starta en editor, t.ex. med kommandot!xemacs. Javaversionen av MATLAB har dessutom en inbyggd editor. En M-fil är en fil som har extensionen.m. I MATLAB-systemet ingår ett antal på förhand definierade M-filer, såsom t.ex. demo.m. För att se vilka filer som finns definierade, använder man kommandot what. Alternativt kan man också använda dir. Det finns också några andra filkommandon i MATLAB, såsom cd, delete och type, som fungerar som motsvarande DOS-kommandon. Med kommandot path får man redan på vilka skivkataloger MATLAB söker igenom för att uppsöka M-filer. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 1
Om man vill tillägga någon katalog till listan, kan man använda kommandona p = path; path(p, d:\matlab ); Samma effekt ger också kommandot addpath d:\matlab. För att läsa in data från en fil kan man använda kommandot load, t.ex. load fname, som läser in filen fname.mat i formatet m rader med n tal i varje rad och lagrar dem som en m n matris med namnet fname. Det finns också ett kommando save för att lagra data i en skivfil. Mera information om sådana kommandon får man med MATLABs help-kommando. Observera, att load och save normalt använder ett binärt format, som inte går att läsa med ett textediteringsprogram. Med optionen -ascii går det att behandla vanliga textfiler. Man kan alltså skriva en matris x i en fil x.dat med en editor, och därpå läsa in den i Matlab med load -ascii x.dat. MATLAB innehåller ett antal kommandon, som gör det möjligt att använda det som ett programmeringsspråk. Sålunda finns det t.ex. villkorssatser och slingor, som påminner om motsvarande kommandon i Pascal, C och Fortran. Vi skall nämna ett antal av dem och illustrera med exempel. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 2
För att göra ett val i MATLAB används if-kommandot, som allmänt kan uttryckas if logiskt uttryck andra kommandon Kommandon, som följer efter if, utförs ast om det logiska uttrycket är sant. Ett logiskt uttryck är oftast en relation av den allmänna formen <aritmetiskt uttryck><relationsoperator><aritmetiskt uttryck>. Det finns sex olika relationsoperatorer: Operator betydelse > större än >= större eller lika med < mindre än <= mindre eller lika med == lika med ~= inte lika med Exempel på sådana relationer är t.ex. a == 0 och x <= 1. Mer komplicerade logiska uttryck får man genom att binda ihop relationer med de logiska operatorerna & (och) (eller) och ~ (negation). Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 3
Exempel på sådana uttryck är x < 2 & x> 0 och x + y >1 x<y, som är sanna om x = 1 och y = 1, men falska om x = 0 och y = 0. Ett logiskt uttryck kan också definieras som en variabel, t.ex. test = x - y < eps, som sedan kan användas i en if-konstruktion (eps är ett litet tal, som anger relativ noggrannhet): test = x - y < eps if ~test z = x + y Detta betyder alltså, pga negationsoperatorn, att instruktionen efter if kommandot utförs, om testvillkoret inte är uppfyllt. Ett sådant if-kommando kan också skrivas på en rad (om det är kort), men det blir lättare att förstå om man använder flera rader. Som ett exempel skall vi se på en del av ett MATLAB-program, som stryker den första kolumnen i en matris, om alla kolumnens element är noll: Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 4
>> a=[0:4; 0:4; 0:4; 0:4] a = 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 >> if a(:,1) == 0 a = a(1:4, 2:5) a = 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 5
if-kommandot kan också kombineras med kommandona else och elseif. Sålunda anger t.ex. if logiskt uttryck instruktioner 1 else instruktioner 2 att kommandona i instruktioner 1 utförs om det logiska uttrycket är sant, medan kommandona i instruktioner 2 utförs om det logiska uttrycket är falskt. I kommandosekvensen if logiskt uttryck 1 instruktioner 1 elseif logiskt uttryck 2 instruktioner 2 kommer kommandona i instruktioner 1 att utföras om logiskt uttryck 1 är sant, medan kommandona i instruktioner 2 kommer att utföras ifall logiskt uttryck 1 är falskt och logiskt uttryck 2 är sant. Observera, att elseif måste skrivas som ett ord. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 6
För att upprepa en följd av programinstruktioner har MATLAB två kommandon, nämligen for och while. Med hjälp av dessa kommandon kan man konstruera slingor. En for-slinga kan uttryckas allmänt på följande sätt: for variabel = uttryck instruktioner I likhet med if-kommandot, kan också for-kommandot skrivas på en rad. I slingkonstruktionen ovan anger variabeln en slingvariabel, som tillordnas ett begynnelsevärde, tillskott och slutligt värde som anges av uttrycket till höger. Vanligen används en kolonbeteckning för att ange detta uttryck, t.ex. i:2:j. Som ett enkelt exempel på en for-slinga skall vi betrakta följande kommandosekvens n = 10; t= 1/(i+j-1) ; for i = 1:n for j = 1:n a(i,j) = eval(t); Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 7
Programmet beräknar en Hilbert-matris av tionde ordningen, vars element ges av formeln A ij = 1 i+j 1. Här anges ett godtyckligt element i matrisen av strängen t, som beräknas (evalueras) med kommandot eval. Observera, att kommandosekvensen innehåller två slingor innanför varandra. Med kommandot while kan man upprepa instruktioner så länge som ett givet logiskt uttryck är sant. Kommandosekvensen avslutas av, liksom for: while logiskt uttryck instruktioner I likhet med for-slingor, kan man också placera while-slingor innanför varandra: while logiskt uttryck 1 instruktioner 1 while logiskt uttryck 2 instruktioner 2 instruktioner 3 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 8
Ett enkelt exempel på en while-slinga är följande, som för ett givet tal a beräknar och skriver ut det minsta ickenegativa heltalet n, som uppfyller villkoret 2 n a: n = 0; while 2^n < a n = n + 1; n Som ett annat exempel skall vi se på följande programfragment, som beräknar en serieutveckling för logaritmfunktionen ur formeln X ( 1) i+1 x i ln(1 + x) = : i i=1 lnsum = 0; x = 0.5; i = 1; while abs((x^i)/i) >= eps lnsum = lnsum + ((-1)^(i+1))*((x^i)/i); i = i + 1; >> format long >> lnsum, i-1 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 9
lnsum = 0.40546510810816 ans = 46 Detta resultat stämmer väl överens med det exakta värdet av ln 1.5: >> ln = log(1.5) ln = 0.40546510810816 Vi har redan tidigare använt oss av funktionsrutiner i MATLAB. Med hjälp av dem kan användaren definiera sina egna funktioner. Låt oss anta att vi behöver en funktion som utför heltalsdivision. Vi kan då editera en fil, som vi kallar t.ex. div.m: function y = div(n,d); % Heltalsdivision: % Ett exempel på en enkel funktionsrutin: % n = rem(n,d) + y.*d, där rem beräknar resten y = (n-rem(n,d))/d; Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 10
Funktionsfiler börjar alltid med kommandot function. Observera användningen av %-tecknet för att skriva kommentarer, som förklarar användningen. En utskrift av dessa kommentarer får man med MATLABkommandot help div. Denna funktion kan användas som vilken annan MATLAB-funktion som helst: >> div(4711,5) ans = 942 >> div(511,4) ans = 127 Ett annat exempel på en funktionsfil är ett litet program, som räknar ut en funktionstabell. Låt oss kalla filen functab.m: Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 11
function Y = Functab(f,a,b,k) % Evaluates a scalar function in [a,b] % at the values x(j) = a + j*k. % The result is a table containing % x-values and f(x) for those x-values. x = a:k:b; z = feval(f,x); Y = [x; z] ; Här har använts kommandot feval med vilket man kan beräkna funktionsvärden. Funktionen är angiven som en sträng f. Programmet kan t.ex. användas på följande sätt för att beräkna en sinustabell: >> tab = Functab( sin,-1,1,0.25); >> tab tab = -1.0000-0.8415-0.7500-0.6816-0.5000-0.4794-0.2500-0.2474 0 0 0.2500 0.2474 0.5000 0.4794 0.7500 0.6816 1.0000 0.8415 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 12
En funktionsrutin kan också ge ut flera argument. Som ett exempel skall vi se på en rutin stat.m, som beräknar medeltalet och standardavvikelsen av en serie tal: function [medel, stav] = stat(x) % STAT - Medeltal och standardavvikelse % Om x är en vektor, så ger stat(x) medeltalet % [medel, stav] = stat(x) ger både medeltal och standardavvikelse % Om x är en matris, så opererar stat(x) på kolumnerna [m n] = size(x); if m == 1 m = n; % behandlar en radvektor medel = sum(x)/m; stav = sqrt((sum(x.^2) - m*medel.^2)/(m-1)); Observera den inbyggda MATLAB-funktionen size, som beräknar antalet rader och kolumner i argumentmatrisen. Funktionen stat går att tillämpa både på vektorer och matriser, såsom framgår av följande exempel: >> x = [1 2 4 8 4 2 1]; >> stat(x) ans = 3.1429 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 13
>> [x1, x2] = stat(x) x1 = 3.1429 x2 = 2.4785 >> x = [1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1] x = 1 2 3 4 5 6 7 8 8 7 6 5 4 3 2 1 >> [x1, x2] = stat(x) x1 = 4.5000 4.5000 4.5000 4.5000 x2 = 2.8868 2.3805 2.3805 2.8868 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 14
Som ett exempel på en något mera komplicerad funktionsfil, skall vi studera ett program, som löser en tredjegradsekvation enligt Cardanos metod. Denna metod, som beskrevs av Girolamo Cardano i Ars Magna år 1545, upptäcktes ursprungligen av Scipione del Ferro och Nicolo Tartaglia i början av 1500-talet. function x = cardan(a,b,c) % CARDAN - lösning av en tredjegradsekvation % x^3 + a x^2 + b x + c = 0 % enligt Cardano % % Konstruktion av hjälpstorheter: p = b-a^2/3; q = c-a*b/3 + 2*a^3/27; r=(q/2)^2 + (p/3)^3; % Tre olika fall behandlas: if r > 0 u = -q/2 + sqrt(r); u = sign(u)*(abs(u))^(1/3); v = -q/2 - sqrt(r); v = sign(v)*(abs(v))^(1/3); x = [u+v-a/3 -(u+v)/2-a/3+i*sqrt(3)*(u-v)/2 -(u+v)/2-a/3-i*sqrt(3)*(u-v)/2]; elseif r < 0 % i detta fall är p<0 u = -q/2 + i*sqrt(-r); v = 2*sqrt(-p/3); x = [v*cos(angle(u)/3)-a/3 v*cos(angle(u)/3+2*pi/3)-a/3 v*cos(angle(u)/3+4*pi/3)-a/3]; else % r=0 u = sign(q)*(abs(q)/2)^(1/3); x = [-2*u-a/3 u-a/3 u-a/3]; Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 15
I programmet uppdelas lösningen på tre fall, beroe på värdet av uttrycket r = ( q 2 )2 + ( p 3 )3. Om detta uttryck är negativt, beror alla rotuttryck av ett komplext tal u, trots att tredjegradsekvationens alla rötter är reella. Funktionen angle(u) ger fasvinkeln för u, dvs φ i u = re iφ. Detta fall, som kallas för casus irreducibilis, studerades av Rafael Bombelli år 1572 och ledde till upptäckten av de komplexa talen. Nedan visas lösningen av Cardanos ekvation x 3 + 6x = 20 enligt denna metod: >> x=cardan(0,6,-20) x = 2.0000-1.0000 + 3.0000i -1.0000-3.0000i >> x.^3+6*x ans = 20.0000 20.0000-0.0000i 20.0000 + 0.0000i Man kan också skriva programfiler, som används interaktivt. Följande exempel visar ett program draw.m som kan användas för att upprita grafen av en funktion, som anges av användaren (observera, att programmet behöver åtminstone MATLAB 4.2): Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 16
% Ett program som ritar funktioner % och skriver förklarande text disp ( Detta program ritar f(x) inom intervallet [a,b] ); % Läs input: ftext = input( Ange en funktion, t.ex. sin(x) :, f ); a = input( Ange nedre gränsen : ); b = input( Ange övre gränsen : ); % Rita funktionen : clf; fplot(ftext, [a b]); Kommandot disp används för att skriva text på skärmen, medan input läser in ett värde eller en textsträng (som i det första fallet, där f ingår i kommandot, varigenom namnet på funktionen inte behöver omges med apostrofer), och samtidigt skriver ut en text. Kommandot clf anger här att bilden töms innan den ritas på nytt. Programmet startas genom att skriva draw, varpå man kan kommunicera med programmet t.ex. på följande sätt: Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 17
Detta program ritar f(x) inom intervallet [a,b] Ange en funktion, t.ex. sin(x) : 2.*exp(-x)*cos(x) Ange nedre gränsen : 0 Ange övre gränsen : 2*pi Bilden ser i detta fall ut på följande sätt: Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 18