• No results found

anv¨andas f¨or att begr¨ansa tillg¨angligheten av t.ex

N/A
N/A
Protected

Academic year: 2021

Share "anv¨andas f¨or att begr¨ansa tillg¨angligheten av t.ex"

Copied!
24
0
0

Loading.... (view fulltext now)

Full text

(1)

forts. p˚a f¨oreg˚aende f¨orel¨asning:

Metoden att g¨omma data, som visades i den nyss beskrivna modulen g¨or programmeringen s¨akrare, och kan ocks˚a t.ex. anv¨andas f¨or att begr¨ansa tillg¨angligheten av t.ex. en databas. N¨ar man skriver en modul, kan man kontrollera variablernas tillg¨anglighet genom att anv¨anda attributen PRIVATE och PUBLIC i deklarationerna, t.ex.

REAL, PRIVATE :: a, x TYPE, PRIVATE :: special

REAL :: p, q, r END TYPE special

Variabler av en h¨arledd typ som ¨ar privat, ¨ar inte tillg¨angliga utanf¨or modulen, d¨ar de definierats, till

˚atskillnad fr˚an v˚art f¨orra exempel, d¨ar komponenterna inte var ˚atkomliga, men d¨aremot typen i sin helhet.

Observera ocks˚a, att ett dubbelkolon (::) m˚aste uts¨attas i en TYPE sats som inneh˚aller attributet PRIVATE eller PUBLIC.

Man kan ocks˚a ange tillg¨angligheten med en s¨arskild PUBLIC- eller PRIVATE-sats:

PUBLIC :: (allm¨ant tillg¨angliga variabler)

PRIVATE :: (ej allm¨ant tillg¨angliga variabler)

(2)

Exemplet med vektorer visar hur man kan skriva moduler f¨or att konstruera nya datatyper och anv¨anda dem i procedurer. ¨Annu mera anv¨andningsbar skulle en dylik programmeringsomgivning bli om man kunde konstruera operatorer som kan till¨ampas p˚a h¨arledda typer.

Vi har t.ex. skrivit en funktionsrutin skal_prod som r¨aknar ut skal¨arprodukten av tv˚a vektorer. Den kan anv¨andas i tillordningssatser av typen a_punkt_b = skal_prod(a,b). Det skulle dock vara naturligare att generalisera multiplikationsoperatorn s˚a att man kunde skriva a_punkt_b = a*b. Detta ¨ar m¨ojligt i Fortran 90 p˚a grund av att man kan definiera nya operatorer (eller utvidga definitionen av de inbyggda operatorerna, vilket ocks˚a kallas f¨or ¨overlagring). Detta g˚ar till p˚a f¨oljande s¨att:

INTERFACE OPERATOR (operatorsymbol) (rutin, som definierar operatorn) END INTERFACE

I denna programkonstruktion kan operatorsymbolen antingen vara en av de inbyggda operatorerna, eller ocks˚a en intill 32 tecken l˚ang teckenstr¨ang, omgiven av punkter. Rutinen som anv¨ands f¨or att definiera operatorn, kan ha antingen ett eller tv˚a argument, men eftersom funktionen normalt definieras i samma modul som inneh˚aller operatordefinitionen, s˚a kan den ers¨attas med satsen MODULE PROCEDURE, som definierar en modulprocedur.

Skal¨arprodukten av tv˚a vektorer kan d˚a definieras med en s¨arskild symbol, t.ex. .punkt.:

(3)

INTERFACE OPERATOR(.punkt.) MODULE PROCEDURE skal_prod END INTERFACE

eller hellre genom en utvidgning av multiplikationsoperatorns betydelse:

INTERFACE OPERATOR(*)

MODULE PROCEDURE skal_prod END INTERFACE

Ett exempel p˚a anv¨andningen av ¨overlagrade operatorer ¨ar ett program, d¨ar man anv¨ander mycket logiska variabler. Man tycker kanske att det ¨ar besv¨arligt att alltid skriva .AND., .OR. och .NOT.. Med hj¨alp av ¨overlagring kan dessa operatorer utbytas mot t.ex. ”*”, ”+” och ”-”. Ett exempel p˚a en modul som

˚astadkommer detta ser vi nedan:

(4)

MODULE logik

INTERFACE OPERATOR(*) MODULE PROCEDURE AND END INTERFACE

INTERFACE OPERATOR(+) MODULE PROCEDURE OR END INTERFACE

INTERFACE OPERATOR(-) MODULE PROCEDURE NOT END INTERFACE

CONTAINS

LOGICAL FUNCTION and(logisk1,logisk2) LOGICAL, INTENT(in) :: logisk1,logisk2 and = logisk1.and.logisk2

END FUNCTION and

LOGICAL FUNCTION or(logisk1,logisk2) LOGICAL, INTENT(in) :: logisk1,logisk2 or = logisk1.or.logisk2

END FUNCTION or

LOGICAL FUNCTION not(logisk) LOGICAL, INTENT(in) :: logisk not = .not.logisk

END FUNCTION not END MODULE logik

(5)

Modulen kan testas t.ex. med f¨oljande program, som ocks˚a visar hur de nya operatorerna kan anv¨andas:

PROGRAM testlog USE logik

IMPLICIT NONE

LOGICAL :: sant=.true.,falskt=.false.

PRINT *, " .true. * .false. =", sant * falskt PRINT *, " .true. + .false. =", sant + falskt PRINT *, "-.true. =", - sant

PRINT *, "Direkt proceduranrop:"

PRINT *, "AND(.true.,.false.)=", AND(sant,falskt) PRINT *, "OR (.true.,.false.)=", OR(sant,falskt) PRINT *, "NOT(.true.) =", NOT(sant)

END PROGRAM testlog

Om man utvidgar betydelsen av en inbyggd operator p˚a detta s¨att, b¨or man minnas, att det ¨ar inte till˚atet att ¨andra betydelsen av den inbyggda operatorn, utan endast att utvidga den. Antalet funktionsargument m˚aste ocks˚a ¨overensst¨amma med vad som g¨aller f¨or den inbyggda operatorn.

(6)

Om man utvidgar betydelsen av n˚agon av relationsoperatorerna < , <= , > , >= , == , /= s˚a kom- mer motsvarande utvidgning av betydelsen ocks˚a att g¨alla de motsvarande alternativa operatorerna .LT.

, .LE., .GT., .GE., .EQ., .NE..

I Fortran 90 har vi ytterligare m¨ojlighet att definiera om tillordningsoperatorn =. Detta beh¨ovs inte om man anv¨ander inbyggda typer, men f¨or h¨arledda typer kan det vara nyttigt, om man vill anv¨anda tillordnings- operatorn f¨or att konvertera mellan olika typer. Tillordningsoperatorn kan definieras analogt med andra operatorer:

INTERFACE ASSIGNMENT(=) (procedur_1)

(procedur_2) END INTERFACE

I modulen som definierar en vektortyp, skulle man kunna anv¨anda rutinerna alstra vektor och vektor racka f¨or att definiera om tillordningen mellan talr¨ackor och vektorer:

INTERFACE ASSIGNMENT(=)

MODULE PROCEDURE alstra_vektor MODULE PROCEDURE vektor_racka END INTERFACE

(7)

Med dessa definitioner ¨ar det m¨ojligt att skriva x = a

b = y

om x, y ¨ar av typ vektor, samt a,b ¨ar talr¨ackor. Observera dock, att vi inte kan variera vektorernas dimensioner i detta fall!

N¨ar man definierar operatorsymboler och tillordningssymboler, l¨onar det sig i allm¨anhet att ”g¨omma” nam- nen p˚a rutinerna som definierar operatorerna, och ist¨allet g¨ora symbolerna allm¨ant tillg¨angliga:

PRIVATE

PUBLIC :: ASSIGNMENT(=)

I FORTRAN 77 hade procedurerna ett ”implicit gr¨anssnitt”, dvs programmeraren b¨or se till att de aktuella argumenten vid anropet av en subrutin svarar mot argumentdeklarationerna i subrutinen. Konstruktionen INTERFACE OPERATOR ... ¨ar ett exempel p˚a ett s.k. ”explicit gr¨anssnitt” (eng. explicit interface), som beh¨ovs f¨or de nya konstruktionerna i Fortran 90. Genom att placera en procedur in i en modul, som kan anv¨andas i en annan programenhet via en USE-sats, ˚astadkommer man ocks˚a ett explicit gr¨anssnitt f¨or ifr˚agavarande procedur.

(8)

Man kan ocks˚a anv¨anda dylika gr¨anssnitt-konstruktioner f¨or att skriva generiska procedurer. Generiska procedurer har vi hittills st¨ott p˚a endast i samband med de inbyggda matematiska funktionerna, s˚asom SIN, COS, ABS, etc, men i Fortran 90 ¨ar det ocks˚a m¨ojligt att definiera egna generiska procedurer, genom att kombinera procedurdefinitioner i ett gr¨anssnitt:

INTERFACE (generiskt_namn) (procedurdefinition_1) ...

END INTERFACE

Vanligen antas procedurerna, som ˚asyftas, ing˚a i en modul och det ¨ar d¨arf¨or tillr¨ackligt att ange namnen p˚a dessa modulprocedurer i gr¨anssnittet, som anges i formen MODULE PROCEDURE namn.

Som ett exempel skall vi studera anv¨andningen av en generisk procedur, som kastar om tv˚a tal, som kan vara antingen heltal eller reella:

(9)

MODULE omkast IMPLICIT NONE INTERFACE byt

MODULE PROCEDURE byt_reella MODULE PROCEDURE byt_heltal END INTERFACE

CONTAINS

SUBROUTINE byt_reella(x,y) IMPLICIT NONE

REAL, INTENT(IN OUT) :: x,y REAL :: tmp

tmp = x x = y y = tmp RETURN

END SUBROUTINE byt_reella SUBROUTINE byt_heltal(x,y)

IMPLICIT NONE

INTEGER, INTENT(IN OUT) :: x,y INTEGER :: tmp

tmp = x x = y y = tmp RETURN

(10)

END SUBROUTINE byt_heltal END MODULE omkast

PROGRAM test_omkast

! Program f¨or att testa modulen omkast USE omkast

IMPLICIT NONE INTEGER :: a, b REAL :: c, d

PRINT *, "Skriv tv˚a heltal:"

READ *, a, b CALL byt(a,b) PRINT *, a,b

PRINT *, "Skriv tv˚a decimaltal:"

READ *, c,d CALL byt(c,d) PRINT *, c,d STOP

END PROGRAM test_omkast

Som vi ser, kan man anv¨anda byt som ett generiskt namn p˚a en rutin, som kastar om tv˚a tal.

(11)

F¨or att reservera globalt minne i Fortran 90 kan man ocks˚a utnyttja moduler, s˚asom t.ex.

module mymod implicit none real :: x

integer :: k, nmax parameter (nmax=1000) real :: y(nmax)

character (len=8) :: namn(nmax) end module mymod

Det reserverade minnesutrymmet kan som synes enkelt ¨andras genom att f¨or¨andra v¨ardet av parametern nmax.

I Fortran 90 ¨ar det ocks˚a m¨ojligt att allokera dynamiskt minne. Detta inneb¨ar, att de definerade talr¨ackorna skall ha ett visst antal dimensioner, men att storleken av dem vid kompileringen inte ¨annu ¨ar k¨and. F¨orst d˚a programmet k¨ors best¨ams antalet element i varje r¨acka.

(12)

I detta fall kan modulen ovan uttryckas module mymod

implicit none real :: x

integer :: k

real, dimension (:), allocatable :: y

character (len=8), dimension (:), allocatable :: namn end module mymod

Minnesallokeringen sker d˚a vid exekveringen genom anv¨andning av allocate-satsen:

use mymod

allocate (y (nmax)) allocate (namn (nmax))

Satsen allocate har i allm¨anhet formen allocate(lista,STAT=ier), d¨ar lista best˚ar av de talr¨ackor f¨or vilka minne skall reserveras, ˚atskilda av kommatecken, och STAT ¨ar en specifikation, som anger om allok- eringen lyckats (ier=0) eller misslyckats (ier>0). F¨or att frist¨alla minnet anv¨ands satsen deallocate.

(13)

Genom att Fortran 90 till˚ater dynamisk minnesallokering, ¨ar det ocks˚a m¨ojligt att definiera rekursiva funktioner, liksom i Pascal. Det klassiska exemplet ¨ar ber¨akningen av fakultetsfunktionen ur rekursions- formeln n! = n · (n − 1)! Denna metod anv¨andes redan i exemplet i avsnitt 2.7, men utan att anropa funktionen rekursivt. Med den rekursiva metoden kan funktionsrutinen skrivas

RECURSIVE INTEGER FUNCTION rfac(n) RESULT (fact) IMPLICIT NONE

INTEGER, INTENT(in) :: n INTEGER :: factorial IF (n<=0) THEN

fact = 1 ELSE

fact = n*rfac(n-1) END IF

END FUNCTION rfac

Som vi ser, kommer funktionen att anropa sig sj¨alv, ¨anda tills argumentet blir 0, resultatet blir 1 och multiplikationskedjan nystas upp. Observera, att resultatet ges namnet fact, f¨or att inte f¨orv¨axling med funktionsnamnet skall ske (detta ¨ar speciellt viktigt ifall resultatet ¨ar en indicerad talr¨acka).

(14)

Vi skall se p˚a ett annat exempel som visar att rekursion inte alltid l¨onar sig. Fibonacci-talen definieras vanligen med hj¨alp av likheterna

f (1) = 1 f (2) = 1

f (n) = f (n − 1) + f (n − 2); n > 2 som leder till en rekursiv funktionsrutin:

recursive function fibonacci (n) result (fibo) implicit none

integer, intent(in) :: n integer :: fibo

if (n <= 2) then fibo = 1

else

fibo = fibonacci (n-1) + fibonacci (n-2) end if

return

end function fibonacci

(15)

Ett program, som testar denna funktion, kan se ut s˚a h¨ar:

PROGRAM fibo_test IMPLICIT NONE INTEGER :: n DO

WRITE (*, ’(A)’, ADVANCE=’no’) ’Ange n: ’ READ (*,*) n

WRITE (*,*) ’n= ’, n IF (n<0) EXIT

WRITE (*,*) ’Fibonacci-talet ¨ar =’, fibonacci(n) END DO

CONTAINS

recursive function fibonacci (n) result (fibo) ...

end function fibonacci END PROGRAM fibo_test

(16)

H¨ar st˚ar funktionsrutinen efter CONTAINS (en ”inre” procedur). Observera ADVANCE=’no’, som anv¨ants i WRITE-satsen. Om n ges ett negativt v¨arde, avslutas programmet.F¨or stora v¨arden av n blir programmet mycket l˚angsamt. H¨ar ges ett exempel p˚a utskriften:

Ange n: 3

n= 3

Fibonacci-talet ¨ar = 2

Ange n: 15

n= 15

Fibonacci-talet ¨ar = 610 Ange n: 30

n= 30

Fibonacci-talet ¨ar = 832040 Ange n: 45

n= 45

Fibonacci-talet ¨ar = 1134903170 Ange n: -1

n= -1

(17)

Denna rekursiva procedur ¨ar inte s¨arskilt effektiv, eftersom m˚anga v¨arden ber¨aknas flera g˚anger. Om man t.ex anv¨ander den f¨or att r¨akna ut f (7), leder detta till ber¨akning av f (6) och f (5). Men ber¨akningen av f (6) leder till ber¨akning av b˚ade f (5) och f (4), s˚a att m˚anga av Fibonacci talen kommer att ber¨aknas p˚a nytt. En effektivare metod f˚as genom att ber¨akna funktionsv¨ardena i tur och och ordning och lagra dem i en dynamiskt allokerad vektor:

function fibonacci (n) result (fibo) implicit none

integer, intent (in) :: n integer :: fibo, i

integer, dimension (:), allocatable :: f if (n <= 2) then

fibo = 1 else

allocate (f (n)) f (1) = 1

f (2) = 1 do i = 3,n

f (i) = f (i-1) + f (i-2) end do

fibo = f (n) end if

return

end function fibonacci

(18)

Denna metod ¨ar snabb, men sl¨osar med minne, eftersom den reserverar en vektor med n element, fast¨an endast de tv˚a senast ber¨aknade talen beh¨ovs. F¨oljande version av programmet, som korrigerar detta problem,

¨ar snabbare ¨an de b˚ada ¨ovriga:

function fibonacci (n) result (fibo) implicit none

integer, intent (in) :: n integer :: fibo

integer :: fi, fi1, i if (n <= 2) then

fibo = 1 else

fi1 = 1 fi = 1 do i = 3,n

fi = fi + fi1 fi1 = fi - fi1 end do

fibo = fi end if

return

end function fibonacci

(19)

De variabler, som hittills behandlats, har alla inneh˚allit n˚agon form av data. Det finns dessutom en annan typ av variabler, som inte inneh˚aller data, men ist¨allet pekar ut den eller de variabler d¨ar data lagras. S˚adana variabler kallas pekare, och de anv¨ands framf¨orallt i s˚adana fall d˚a data alstras och f¨orintas dynamiskt.

Pekare anv¨ands ocks˚a f¨or att underl¨atta manipulationer med stora m¨angder data, eftersom det ¨ar mycket l¨attare att flytta pekare ¨an data.

I Fortran deklareras en variabel som en pekare med hj¨alp av attributet POINTER, t.ex. satsen REAL, POINTER :: a betyder att a ¨ar en pekare som pekar p˚a objekt av reell typ (n¨armare best¨amt endast objekt av reell typ). Pekare kan ocks˚a definieras s˚a att de pekar p˚a objekt av h¨arledda typer, t.ex. TYPE (medlem), POINTER :: q f¨orklarar q vara en pekare p˚a ett objekt av typ medlem. Varje pekare har dessutom en status, som anger om den f¨or tillf¨allet pekar p˚a n˚agonting. Denna status ¨ar ursprungligen odefinierad.

Emedan anv¨andningen av pekare l¨att kan p˚averka negativt programeffektiviteten, kr¨aver man dessutom att en pekare inte kan peka p˚a vilken som helst variabel av en given typ, utan att objekten som den pekar p˚a m˚aste ha ytterligare ett attribut, som kallas TARGET (”m˚alet”). Detta kan vi belysa med ett exempel:

INTEGER, POINTER :: q REAL :: a

REAL, TARGET :: b REAL, POINTER :: c

(20)

H¨ar ¨ar c en pekare, som kan peka p˚a b men inte p˚a a, eftersom den saknar m˚alattribut. Pekaren c kan ˚a andra sidan inte heller peka p˚a q, eftersom den har fel typ.

En pekare associeras med m˚alet via en pekartillordningssats, som har formen pekare=>m˚al. Observera, att tillordningsoperatorn ¨ar en sammansatt symbol, som best˚ar av ett likhetstecken och ett st¨orre ¨an-tecken (utan mellanrum). N¨ar pekaren pekar p˚a ett m˚al, s¨ages den vara associerad. Som ett exempel kan vi se p˚a f¨oljande program, som illustrerar dessa begrepp:

Program pektest implicit none

integer, pointer :: r, s integer, target :: t integer :: q

t = 1 r => t t = 3 s => t q = r*s

print *, r, s, t, q stop

End program pektest

(testa g¨arna programmet, och studera utskriften).

(21)

M˚alet f¨or en pekare kan givetvis ocks˚a vara en vektor, eller en matris. S˚alunda betyder t.ex. satsen REAL, DIMENSION(:), POINTER :: p v att p v pekar p˚a vektorer. En av de viktigaste anv¨andningarna av en vektorpekare ¨ar m¨ojligheten att dynamiskt alstra minne n¨ar det beh¨ovs, och frist¨alla det n¨ar det inte l¨angre beh¨ovs. Detta utf¨ors med ALLOCATE-satsen som vi redan tidigare st¨ott p˚a.

Den har f¨oljande form: ALLOCATE (pekare (dimension), STAT=status) d¨ar pekaren nu ¨ar en vektorstorhet, som har b˚ade dimensions- och pekarattribut, och status ¨ar en heltalsvariabel, som f˚ar v¨ardet 0 om allt lyckas.

En vanlig anv¨andning av pekare ¨ar i en s.k. l¨ankad struktur (f¨orekommer t.ex. i simuleringsprogram), d¨ar varje objekt pekar ut n¨asta objekt (typen kallas nod):

TYPE nod

INTEGER :: tal

TYPE (nod), POINTER :: nasta END TYPE nod

(22)

Denna typdeklaration definierar en enkel l¨ankad lista med tv˚a noder d¨ar varje nod inneh˚aller ett heltal och en l¨ank till n¨asta nod. Den sista noden pekar p˚a ett tomt m˚al, vilket man alstrar med satsen NULLIFY.

Som vi ser, kommer TYPE(nod) :: p

TYPE(nod), TARGET :: q p = q

att vara detsamma som p%tal = q%tal

p%nasta => q%nasta

En l¨ankad lista med noder av ovanst˚aende typ som avslutas med ett tomt m˚al skulle kunna konstrueras p˚a f¨oljande s¨att:

(23)

PROGRAM lankadlista IMPLICIT NONE TYPE nod

INTEGER :: tal ! data

TYPE (nod), POINTER :: nasta ! pekaren END TYPE nod

TYPE (nod), POINTER :: lista, aktuell INTEGER :: n, stat

NULLIFY(lista) !nollst¨all listan

DO

READ *, n ! l¨as v¨ardet av n

IF (n==0) EXIT ! sluta d˚a n = 0

ALLOCATE(aktuell, STAT=stat) ! alstra en ny nod IF (stat > 0) STOP ’ingen ny nod allokerades’

aktuell%tal=n ! ins¨att n som v¨arde i aktuell nod aktuell%nasta => lista ! peka p˚a den tidigare noden

lista => aktuell ! uppdatera b¨orjan av listan END DO

PRINT *, ’G˚a igenom listan och skriv ut v¨arden’

aktuell => lista ! g¨or den aktuella noden till listans alias DO

IF (.NOT. ASSOCIATED(aktuell)) EXIT ! hoppa ut om pekaren visar p˚a noll PRINT *, aktuell%tal ! Skriv ut v¨ardet

aktuell => aktuell%nasta ! g¨or den aktuella noden till n¨asta END DO

END PROGRAM lankadlista

(24)

I b¨orjan ¨ar listan tom, och lista pekar d¨arf¨or b˚ade p˚a b¨orjan och slutet. Detta ˚astadkommes genom att nollst¨alla listan med NULLIFY, som tar bort pekarens association. D¨arp˚a l¨aser man in ett heltalsv¨arde (n), och listan initialiseras med en nod, som inneh˚aller detta v¨arde. Detta sker genom att f¨orst reservera dynamiskt minne f¨or den aktuella noden med ALLOCATE. Denna f˚ar d˚a talv¨ardet n. Till slut f˚ar lista peka p˚a b¨orjan av listan som ¨ar den aktuella noden som just blivit allokerad. Processen upprepas ¨anda tills v¨ardet 0 blivit inl¨ast. Om talen 1,2,3 blivit inl¨asta (i denna ordning) blir listan →(3/nasta)→(2/nasta)→(1/noll).

Till slut g˚ar man igenom listan och skriver ut alla v¨arden. Till att b¨orja med l˚ater man den aktuella noden pe- ka p˚a den f¨orsta noden, som skrivs ut. D¨arp˚a f˚ar den aktuella noden peka p˚a n¨asta nod, och man g˚ar till b¨or- jan av DO–slingan. Om den aktuella noden ¨ar associerad (testas med funktionen ASSOCIATED(aktuell)), s˚a skrivs den ut, om inte, s˚a har vi kommit fram till listans slut.

Fortran 90 ger, som vi har sett, en m¨ojlighet att definiera nya datatyper, och s¨atta in dem i moduler, konstruera nya operatorer och definiera nya metoder att tillordna variabler v¨arden, konstruera pekare, och att anv¨anda attribut s˚asom PUBLIC och PRIVATE f¨or att kontrollera tillg¨angligheten av olika definitioner.

Dessa nya metoder kallas i allm¨anhet data-abstraktion, som ¨ar betydelsefull i all modern programmering.

Aven om Fortran 90 inte fullt underst¨¨ oder s.k. objekt-orienterad programmering, som nu ¨ar p˚a modet, s˚a inneh˚aller spr˚aket dock f¨oruts¨attningar d¨arf¨or, och nya Fortran-standarder utvecklas mer och mer i denna riktning.

References

Related documents

Detta g¨aller alla tal vars dyadiska utveckling ¨ar ¨andlig; man beh¨over inte kasta fler kast ¨an vad som anges av den position d¨ar sista ettan finns i utvecklingen.. Det betyder

Man kan faktiskt g¨ora ett konfidensintervall f¨or medianen med konfidensgrad minst lika med 1 − α helt utan n˚ agra som helst antaganden om den bakom- liggande f¨ordelningen

D¨ arf¨ or ska vi ber¨ akna den betingade sannolikheten att vi drar ask A, givet att vi har erh˚ allit ett 1-euro mynt. Antingen f˚ ar vi sexa eller inte vid varje

Till exempel fick jag inte med n˚ agot Ljus- och Optikland i f¨ orsta f¨ ors¨ oket, och pilen mot Kosmologi, som ligger utanf¨ or den h¨ ar kartan, borde peka mer upp˚ at,

Anv¨ andningsfall/Scenario En anv¨ andare skall kunna v¨ alja att spela med en annan anv¨ andare Utl¨ osare Anv¨ andaren v¨ aljer att spela

[r]

[r]

Utbytesalgoritmen anv¨ ands f¨ or att ber¨ akna en approximation till en konvex funktion f ∈ C[a, b] ur m¨ angden P 1 , dvs.. ur m¨ angden av f¨ orstagradspolynom p˚