Matlabövning 1 Funktioner och grafer i Matlab I den här övningen ska vi titta på hur man konstruerar funktioner i Matlab och hur man kan rita funktionsgrafer. Läs först igenom PM:et. Gå sedan igenom exemplen och gör övningarna. Dokumentera koden från uppgifterna i m-filer. Redovisning av genomförd laboration görs i första hand vid övningstillfället, i andra hand via skriftlig rapport. Se till att försöka besvara eventuella frågor. Definiera funktioner i Matlab I Matlab finns det en hel del matematiska funktioner fördefinierade, som t.ex. exp som är den naturliga exponentialfunktionen, exp(3) ger till exempel som värde e 3. Matlabhjälpen har en lista på alla inbyggda funktioner. Ofta vill man definiera en egen funktion och ge den ett namn så man kan använda den på samma sätt som de inbyggda. Det finns ett par olika sätt att definiera en funktion. Funktions-m-filer Det klassiska sättet är att definiera funktionen i en m-fil. Man skapar en fil i matlabs arbetsmapp (eller någon annanstans i de mappar som finns i variabeln matlabpath) med funktionens namn plus ändelsen.m som filnamn. Matlab har en inbyggd editor för m-filer, under File -menyn, tag New för att skapa en ny m-fil. Det kan också göras genom att skriva edit filnamn.m i kommandofönstret. En m-fil kan antingen vara en skriptfil eller en funktionsfil. En scriptfil består av matlabkod som körs rätt upp och ned, då skriptet anropas med sitt filnamn. En funktionsfil kännetecknas av att första raden är en funktionsdeklaration. Innehållet i en funktionsfil kan se ut på följande sätt: function y=kvadrat(x) % Allt som står efter ett %-tecken på en rad är en kommentar, % och hoppas över av matlab. y = x.^2; % Vi använder.^ för fält(array)versionen av potens, % om argumentet är en vektor eller en matris så kvadreras % varje element i x. med ^ hade det varit matrispotens. % Motsvarande gäller multiplikation (.*,*) och division(./,/) På första raden deklarerar man att det är en funktion och vad argument och funktionsvärde har för variabelnamn i den följande koden. Den börjar med ordet function följt av ett variabelnamn för funktionsvärdet (i det här fallet y), ett likhetstecken, funktionsnamnet (samma som filnamnet, är de olika är det filnamnet som räknas) och inom parentes ett eller flera variabelnamn för funktionens argument (x i det här fallet). 1
Efter den första raden följer matlabkod som exkeveras när funktionen anropas. De variabler som angetts som argument kommer att ha de värden som funktionen anropats med, i vårt exempel, om funktionen anropas som kvadrat(2), så kommer, när funktionsfilens kod körs, x att ha värdet 2. När koden är exekverad, ska variabeln som deklarerats som funktionsvärde ha fått det värde den ska ha. Koden kan dock göra mycket annat än att bara tilldela ett funktionsvärde. Alla övriga variabler i en funktionsfil är lokala, dvs tilldelar man en variabel ett värde i funktionskoden, så finns det inte som värde utanför, och tvärtom. Vill man skicka variabelvärden mellan funktionen och utsidan måste de deklareras som global, både innanför och utanför. (Vi går inte in på det här.) En sak som man särskilt bör tänka på när man använder uttryck på vektorer/matriser (arrays) är att matlab använder *, /, och ^ för matrisoperationer, medan.*,./ och.^ gör multiplikation, division respektive potenser elementvis i lika stora matriser. Listor av koordinater som man skickar till plot är i matlabs ögon matriser (med en rad), där man normalt vill göra operationerna elementvis. Ex: [1 2 3 4].*[5 2 4 3] ger [5 4 12 12] medan [1 2 3 4]*[5 2 4 3] ger felmeddelande eftersom man inte kan matrismultiplicera en 1 4-matris med en 1 4-matris. ([1 2 3 4] *[5 2 4 3] ger däremot en 4 4-matris. Operatorn transponerar en matris). De flesta av matlabs inbyggda funktioner verkar elementvis på matriser. Om x är en matris ger t ex y=sin(x) en lika stor matris y med element som är sinusfunktionens värden för respektive element i x. Pröva t ex med y=sin([0,pi/4,pi/2,3*pi/4,pi]). Anonyma funktioner En funktion kan också definieras som en s.k. anonym funktion. Vi kan definiera en kvadreringsfunktion som ovan genom nykvadrat = @(x)x.^2; Uttrycket @(x)x.^2; skapar en anonym funktion som avbildar x på x 2. Sedan tilldelar vi variabeln nykvadrat ett värde som är ett handtag (handle) till funktionen, så vi kan använda den med namnet nykvadrat. nykvadrat(3) ger alltså värdet 9. En anonym funktion konstrueras alltså genom att efter ett @ ange argumentet (eller flera med komman emellan) inom parentes, och därefter ett uttryck som beräknar funktionsvärdet. Som ett exempel på en konstruktion som beräknar summan av två argument har vi addera=@(a,b)a+b; addera(3,4) ger då värdet 7. Inline-funktion Ett alternativt sätt, är genom funktionen inline, som definierar en funktion utifrån en textsträng, som t.ex. enkvadrattill=inline( x.^2, x ); 2
Man anger alltså en textsträng med ett uttryck för funktionsvärdet, därefter en textsträng med argumentets namn (kan utelämnas, då gör matlab en mer eller mindre intelligent gissning). Det här är en gammal konstruktion, använd hellre varianten med @. Uppgift 1. Definiera funktionen f(x) = x 3 x dels som en funktionsfil, dels som en anonym funktion. Ge de tre funktionerna olika namn. Se till att de fungerar elementvis för vektorer. Skapa vektorn x=-2:0.5:2 och beräkna funktionsvärdena för talen i x med var och en av de tre versionerna av funktionen. Uppgift 2. Om du inte tidigare gjort det, definiera kvadratfunktionen som ovan, på något av de tre sätten. Skapa en ny funktion (t.ex. som en anonym funktion) som sammansättningen av kvadratfunktionen som inre funktion och f från ovan som yttre funktion. Ge den ett lämpligt namn, och beräkna dess värden på vektorn x som ovan. Rita grafer Vi ska här titta på två matlabfunktioner för att rita grafer, dels plot som är en generell funktion för att plotta punkter och kurvor, dels fplot som är speciellt för att rita funktionsgrafer. Givet två vektorer x och y med samma antal element, n st, så skapar plot(x,y) n punkter genom att i tur och ordning ta koordinater från x respektive y. Som default ritar plot en kurva i blått genom att förbinda punkterna med linjer. Detta kan ändras, genom att ange hur punkterna och linjerna emllan ska se ut, exempelvis ger plot(x,y, ro: ) en kurva i rött med prickad linje, och varje punkt markerad med en cirkel. (Se vidare i manualen.) Exempel: p=plot([1,2,4,3],[0,3,2,1], ko- ); Plotfunktionen returnerar ett värde, som kan användas för att komma åt detaljer i den senare. I exemplet ovan ges alltså p ett handle-värde för kurvan. Man kan t.ex. ändra hur kurvan ritas ut, exempelvis genom set(p, marker, * ) som ändrar punktmarkeringarna till stjärnor. Om man ska använda plot för att rita en funktionsgraf, skapar man först en vektor med ett urval av x-koordinater, sedan beräknar man utifrån den motsvarande funktionsvärden som y-koordinater. Dessa båda vektorer använder man sedan plot på. För att få en vektor med ett jämnt fördelat antal tal över ett intervall kan man använda linspace. linspace(a,b,n ) ger en vektor med n tal jämnt fördelade från a till b. Exempel: x=linspace(0,2*pi,100); y=sin(x); plot(x,y, o- ); ger oss en graf genom att beräkna funktionsvärden för sinus i hundra punkter i intervallet [0, 2π]. Man kan också använda konstruktionen x=a:d:b som ger en vektor där första talet är a, andra a+d, nästa a+2d, osv, tills man nått b. Ex: x=[0:0.05:2*pi]; Uppgift 3. Rita med plot graferna för funktionerna du definierat i de tidigare uppgifterna på intervallet [ 2, 2], genom att använda ett lagom antal punkter. Matlabfunktionen fplot tar inte vektorer med explicita punktkoordinater, utan istället 3
en fördefinierad funktion och ett intervall, bestämmer sedan själv vilka punkter som funktionen skall beräknas i och ritar en graf. Funktionen anges med sitt handle, dvs det som man får om man använder konstruktionen med anonym funktion. För matlabs inbyggda funktioner och funktioner man definierat som m-filer får man handtaget genom att sätta @ framför namnet. Definitionsintervallet anges som en vektor med två element, vänstra respektive högra ändpunkten. Exempel: fplot(@sin,[0,2*pi], +- ); Uppgift 4. Upprepa förra uppgiften genom att använda fplot. Plotfunktionerna raderar normalt det som tidigare ritats innan de ritar sitt. För att behålla det gamla, skriv hold on innan du plottar. För att återställa, skriv hold off. Man kan när som helst radera det aktuella grafikfönstret med clf (clear figure) Om inte omfånget på axlarna är vad som passar kan det ändras med xlim([xmin,xmax ]) respektive ylim([ymin,ymax ]). (Eller sammanslaget som axis([xmin,xmax,ymin,ymax ].) Uppgift 5. Rita graferna y = sin x och y = cos x på intervallet [0, 4π] i samma koordinatsystem. Använd olika färger och olika linjetyp för de två graferna. Välj lagom många punkter i intervallet. Uppgift 6. Rita graferna y = sin x och y = 1.2 sin (2x + π/3) på intervallet [0, 4π] i samma koordinatsystem. Använd olika färger och olika linjetyp för de två graferna. Uppgift 7. Rita, med hjälp av plot, grafen för y = sin(50x) på intervallet [0, 2π] med några olika val av antal punkter, jämför särskilt mellan 50, 51, 52 osv, samt 99, 100 och 101 punkter (använd linspace(0,2*pi,n). Vad beror skillnaden på? Hur ser grafen egentligen ut? Uppgift 8. Rita en enhetscirkel i ett koordinatsystem. Detta görs lämpligen genom att skapa en lämplig vektor t och sedan skapa vektorerna x=cos(t) och y=sin(t). För att cirkeln ska bli visuellt rund kan man sätta samma skala på båda koordinataxlarna genom axis equal, efter att man använt plot. Rita sedan i samma koordinatsystem en cirkel med mittpunkt i (1, 2) och radien 3, i en annan färg. Uppgift 9. Konstruera en m-fil som implementerar funktionen 1 (x + 1) 2 om x < 1, g(x) = 1 om 1 x 1, 1 (x 1) 2 om x > 1. Rita funktionens graf på intervallet [ 2, 2]. Tips: Använder man en jämförelse på en vektor v får man en vektor som är 1 där jämförelsen är sann och 1 där den är falsk. Till exempel ger x = -2:0.5:2; z = (x<=1) & (x>=-1); vektorn z = [0 0 1 1 1 1 1 0 0]. Som exempel kan man implementera funktionen x om x < 0, x x 2 om 0 x < 0, x 3 om 1 x, 4
genom (x<0).*x + (0<=x & x<1).*x.^2+(x>=1).*x.^3. Observera parenteserna runt de logiska uttrycken, som behövs eftersom logiska operatorer (som &) har lägre prioritet än aritmetiska (som.*). Man kan istället använda en konstruktion med if/elseif/else/end (se dokumentationen), men det ställer till problem om funktionen skall användas på vektorer (arrays). Går dock att lösa med hjälp av arrayfun. 5