Komplexa tal
Komplexa tal med DSL
Då inleder vi med komplexa tal! Det här är något som antagligen känns ganska hemvant för de flesta av er men vi tar och repeterar lite ändå och passar på att visa hur man kan implementera ämnet med DSL.
Imaginära tal. Var kommer dom ifrån tänker ni? Jo, det är så att om man försökte dra roten ur ett negativt tal så blev det jobbigt, fram till att någon introducerade imaginära tal. Som är jobbiga på sitt eget sätt istället. Så därför bestämdes det att ska vara -1.
Som tur är så är det hela ganska konsekvent utformat så att också blir , och blir . Så om man drar roten ur vilket negativt tal som helst så får man samma svar som i det positiva fallet fast med ett i på köpet.
Vi kommer dock inte använda oss av beteckningen i i våra texter, eftersom att man inom fysik, elektronik och flera andra ämnen redan använder bokstaven i för att beteckna en ström. Därfor brukar man ofta använda j inom signallära istället, för att undvika missförstånd, och det kommer vi också göra. Komplexa tal kan ses som ett par utav reella värden, där första värdet i talet är reellt och det andra värdet är den imaginära delen. Det kan dock vara så att en eller båda av dessa delar är noll. T.ex. blir ju bara 7.
Kryssfråga 1: Vad är den reella delen av ?
- a) 5
- b) 10
Rätt svar!
Fel svar!
Kryssfråga 2: Vad är den imaginära delen i talet ?
- a) 4
- b)
Rätt svar!
Fel svar!
Att skriva
Complex 13 37i vårt DSL är samma sak som att skriva , där 13 är reellt och 37 är imaginärt. Det är alltså inget ‘j’ i vårt DSL som indikerar att det är imaginärt utan man måste bara skriva dem i rätt ordning. Det ser som tur liknande ut i matten så det är ganska lätt att komma ihåg! Nu betraktar vi det komplexa talet . Vi döper detta till leet så att vi slipper skriva ut alltihop i framtiden.
ghci> let leet = Complex 13 37Om du nu känner att du vill veta vad det reella talet i paret är, då kan man skriva en funktion realPart som bara ger dig den reella delen.
realPart :: Complex -> Double
realPart (Complex re im) = reNu kan vi enkelt få ut realdelen ifrån leet:
ghci> realPart leet
13Se så enkelt det blev! Så för att få ut den imaginära delen av talet så gör vi en funktion imPart.
Övning 1: Definiera en funktion imPart som ger imaginärdelen av ett komplext tal. Denna funktion bör ge: imPart (leet) = 37.
imPart :: Complex -> Double
imPart (Complex re im) = imÖvning 2: Om vi nu skulle vilja skriva ut talet på vanligt mattespråk så skulle vi kunna göra en funktion som kan heta printComplex. Här får du ett kodskelett för en sådan funktion. Fyll i det som saknas.
printComplex :: Complex -> String
printComplex z
| re == 0 = show im ++ "j"
| im == 0 = undefined
| otherwise = undefined
where im = imPart z
re = realPart zprintComplex :: Complex -> String
printComplex z
| re == 0 = show im ++ "j"
| im == 0 = show re
| otherwise = show re ++ " + " ++ show im ++ "j"
where im = imPart z
re = realPart zExempel:
ghci> printComplex (Complex 5 12)
"5 + 12j" ghci> printComplex leet
"13 + 37j"Hur skulle man då göra för att faktiskt räkna på detta? Då måste man definiera hur matematiska tecken ska tolkas när man arbetar med komplexa tal.
Addition för komplexa tal är ganska lätt om ni kommer ihåg det. Om man är reell bryr man sig bara om andra reella tal, och vice versa för imaginära tal.
Övning 3: Här får du ett kodskelett för addition med komplexa tal. Fyll i det som ska stå i parentesen.
instance Num Complex where
z + w = Complex (...)instance Num Complex where
z + w = Complex (realPart z + realPart w) (imPart z + imPart w)Test 1: Vad får man om man adderar med ? Testa med programmet. Svara utan mellanrum! a+bj
Rätt svar!
Fel svar!
Multiplikation blir lite krångligare. Om vi multiplicerar två komplexa tal, vi kallar dem z och w, ser det ut såhär:
z * w = Complex (realZ*realW - imZ*imW) (realZ*imW + realW*imZ)
where realZ = realPart z
realW = realPart w
imZ = imPart z
imW = imPart wVilket då blir samma sak som:
Rätt svar!
Fel svar!
Det kan även vara bra att ha en funktion som negerar ett komplext tal. T.ex. ska då alltså bli
Övning 4: Här är ett kodskelett till funktionen negate. Fyll i det som ska stå i parentesen.
negate z = Complex (...) negate z = Complex (negate $ realPart z, negate $ imPart z)Absolutbeloppet på ett komplext tal kan man räkna ut på samma sätt som man räknar ut hypotenusan i en rätvinklig triangel.
Övning 5: Här är ett kodskelett till en funktion som ger absolutbeloppet av ett komplext tal. Fyll i det som saknas.
abs z = Complex hyp 0
where hyp = ...
re = realPart z
im = imPart z abs z = Complex (hyp, 0)
where hyp = sqrt (re*re + im*im)
re = realPart z
im = imPart zTest 3: Vad är absolutbeloppet av ? Testa med programmet. Svara med 4 värdesiffror.
Rätt svar!
Fel svar!
Test 4: Hur skriver man ut heltalet 5 som ett komplext tal? Testa med programmet (fromInteger).
Rätt svar!
Fel svar!
Eulers formel
Eulers formel, eller Enigmatic Euler’s Formula som den också kallas, är en formel för att skriva om komplexa tal från en exponentiell funktion till trigonometriska funktioner och tvärtom.
Är det någon som verkligen vet hur trigonometriska funktioner funkar? Förmodligen..., men det skulle väl inte skada om det fanns ett sätt att skriva om trigonometriska funktioner till komplexa tal och tvärtom. Här kommer Eulers formel in!
Kryssfråga 3: Vad blir omskrivet med Eulers formel?
- a)
- b)
- c)
Rätt svar!
Fel svar!
Kryssfråga 4: Vad blir omskrivet med Eulers formel?
- a)
- b)
- c)
Rätt svar!
Fel svar!
Med lite magiska omskrivningar kan man bryta ut cosinus respektive sinus ur formeln vilket ger följande funktioner. Varför skulle flera komponenter vara bättre då? Det tar vi upp i avsnitt 3 om Fourierserier! Men nu vet ni hur man gör!
Sammanfattning
Gratulerar! Du har nu lärt dig följande:
Vad komplexa tal är.
Hur man gör några vanliga beräkningar med komplexa tal.
Hur man implementerar komplexa tal med funktionell programmering i en DSL.
Hur man implementerar vanliga beräkningar med komplexa tal med funktionell programmering i en DSL.
Vad Eulers formel är.
Hur man kan skriva om trigonometriska och komplexa uttryck med Eulers formel.
Hur man implementerar Eulers formel med funktionell programmering i en DSL.
Introduktion Signaler
