READ (*, 100) X,Y,Z,T,U,V 100 FORMAT (6F5.2) för att läsa in talen 1.8 6.5 14.9 5.1 1.2 0.4 17.4 25. 4. -6.1 4.8-7.8



Relevanta dokument
2.4. Teckensträngar och logiska uttryck

Enklast att skriva variabelnamn utan ; innehåll och variabelnamn skrivs ut

Textsträngar från/till skärm eller fil

Datorlära 3 Octave Workspace ovh mijlö Skriva text på skärmen Värdesiffror Variabler och typer Strängar Makro Vektorer

5 Grundläggande in- och utmatning

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Tentamen OOP

Föreläsning 6: Introduktion av listor

Objektorienterad programmering D2

Föreläsning 1 & 2 INTRODUKTION

TAIU07 Matematiska beräkningar med Matlab

Inledande programmering med C# (1DV402) 27+15=42 1 (22)

Repetition av filer Grundkurs i programmering med Python

1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

Institutionen för datavetenskap 2014/15

Introduktion till integrering av Schenkers e-tjänster. Version 2.0

Föreläsning 3.1: Datastrukturer, en översikt

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

1 Funktioner och procedurell abstraktion

Programmeringsteknik med C och Matlab

MMA132: Laboration 1 Introduktion till MATLAB

Introduktion till vetenskapliga beräkningar II, Tom Sundius

Exempel på ett litet Ada-program

SMD 134 Objektorienterad programmering

Objektorienterad programmering i Java

Matematisk Modellering

Lösningar till tentauppgifterna sätts ut på kurssidan på nätet idag kl 19. Omtentamen i Programmering C, 5p, fristående, kväll,

Tentamen DE12, IMIT12, SYST12, ITEK11 (även öppen för övriga)

Pascal... Pascal. Pascal... Pascal...

Algoritmanalys. Genomsnittligen behövs n/2 jämförelser vilket är proportionellt mot n, vi säger att vi har en O(n) algoritm.

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

TATA42: Föreläsning 10 Serier ( generaliserade summor )

KPP053, HT2015 MATLAB, Föreläsning 1. Introduktion till MATLAB Skript Inläsning och utskrift av variabler Ekvationssystem Anonyma funktioner

Hjälpmedel för kompilatorkonstruktion, DVB004

3.3. Symboliska matematikprogram

Kapitel 15: Data/Matrix Editor

Inlämningsuppgift 4 NUM131

2.2. Ett enkelt Fortran-program

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Programmeringsuppgifter 1

Enkla datatyper minne

Övningar i JavaScript del 2

Ickelinjära ekvationer

Tentamen Grundläggande programmering

Grunderna i stegkodsprogrammering

Uppgift (poäng) 1 (2) 2 (3) 3 (4) 4 (4) 5 (3) 6 (4) 7 (6) 8 (6) 9 (8) Summa

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

Grundläggande programmering med C# 7,5 högskolepoäng

Björn Abelli Programmeringens grunder med exempel i C#

4 Sammansatta datatyper

1 Datorn som miniräknare. 1.1 Räkneoperationer. 1.2 Variabler

STYRNING AV PORTFÖLJER MED FLERA TILLGÅNGAR

a), c), e) och g) är olikheter. Av dem har c) och g) sanningsvärdet 1.

Approximation av funktioner

Föreläsning 4: Poster

Chapter 3: Using Classes and Objects

Lektion 1, del b Utskrifter av variabelvärden Inläsning av värden till variabler

4.3. Programmering i MATLAB

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten 2010

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Projekt: Basketbollkast

Föreläsning 8: Aritmetik och stora heltal

Översikt över Visual Basic

Objektorienterad programmering Föreläsning 11. Copyright Mahmud Al Hakim

Repetitionsuppgifter i Matematik inför Basår. Matematiska institutionen Linköpings universitet 2014

Anvisningar för ifyllning av Excelark för databaser (sekventiella textfiler)

Språket Python - Del 1 Grundkurs i programmering med Python

6.3. Direkta sökmetoder

Programmering A. Johan Eliasson

Tips och tricks 1 Cadcorp SIS

Grunderna i SQL del 1

16 Programmering TI -86 F1 F2 F3 F4 F5 M1 M2 M3 M4 M5

COBOL. från grunden. monitors. Peter Sterwe. training people

Tentamen i. för D1 m fl, även distanskursen. fredag 13 januari 2012

Tänk på följande: Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Introduktion till formella metoder Programmeringsmetodik 1. Inledning

Uppgift 1 (Oläsliga krypterade meddelanden)

Beräkningsvetenskap föreläsning 2

Att använda pekare i. C-kod

TDIU01 - Programmering i C++, grundkurs

Introduktion. Exempel Övningar Lösningar 1 Lösningar 2 Översikt

Introduktion till programmering SMD180. Föreläsning 2: Variabler, uttryck och satser

Dynamisk HTML JavaScript och webbläsarens objektmodell

Övningar Dag 2 En första klass

Matematisk statistik allmän kurs, MASA01:B, HT-14 Laboration 2

Tentamen TANA17 Matematiska beräkningar Provkod: DAT1 Godkänd: 8p av totalt 20p Tid: 14:e januari klockan

Introduktion till Winbas. produkt och prisinläsning

Seriehantering. [En enkel guide för hur du som serieadministratör använder SVEMO TA.]

DD1361 Programmeringsparadigm. Carina Edlund

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Omtentamen i DV & TDV

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Översikt. Installation av EasyPHP 1. Ladda ner från Jag använder Release Installera EasyPHP.

ANDREAS REJBRAND Matematik Numeriska serier. Andreas Rejbrand, april /29

Tentamen i Objektorienterad programmering

STADSBYGGNADSFÖRVALTNINGEN. Aktivitetsstöd. Behörigheten Föreningsadministratör. Datum: Version 2. Sidan 1 (30)

MATLAB the Matrix Laboratory. Introduktion till MATLAB. Martin Nilsson. Enkel användning: Variabler i MATLAB. utvecklat av MathWorks, Inc.

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Objektorienterad Programmering (TDDC77)

Digitalitet. Kontinuerlig. Direkt proportionerlig mot källan. Ex. sprittermometer. Elektrisk signal som representerar ljud.

Transkript:

forts. på föregående föreläsning: I allmänhet lönar det sig att sätta ut decimalpunkterna för reella tal. Om man inte enkelt kan skriva talen under varandra så kan det lätt uppstå fel vid inmatningen, vilket visas av följande exempel. Antag, att vi använder READ-satsen READ (*, 100) X,Y,Z,T,U,V 100 FORMAT (6F5.2) för att läsa in talen 1.8 6.5 14.9 5.1 1.2 0.4 17.4 25. 4. -6.1 4.8-7.8 Vid läsningen av den andra raden uppstår då ett fel (kan du se var?). Om inmatningen sker från en terminal, är det därför oftast bekvämare att använda ett fritt format (som anges med en asterisk (*)). När man läser in teckensträngar, räcker det med att använda A-formatet som sådant, utan att ange antalet tecken, eftersom teckensträngens längd anges i CHARACTER-deklarationen. Inga extra tecken kommer således att läsas in. Ett mindre antal tecken kan man däremot nog läsa in, såsom framgår av nedanstående exempel: Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 1

CHARACTER (10) :: A... READ (10, 100) A 100 FORMAT (A1)... Här läses endast första tecknet in i A, de övriga 9 tecknen fylls ut med blanka tecken. Om det finns fält som man inte vill läsa in, kan man använda X-specifikationen (eller TR-specifikationen), som framgår av exemplet nedan: READ (5,100) X, Y 100 FORMAT (F5.2, 7X, F8.4) Man kan också hoppa över hela poster vid inmatningen, genom att använda formatspecifikationen /. Observera i detta fall, att t.ex. instruktionen READ (5, 100) X, Y 100 FORMAT (F5.2/F10.4) kommer läsa X från en post och Y från följande. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 2

Vill man verkligen hoppa över en post mellan X och Y, måste man använda formatet 100 FORMAT (F5.2//F10.4). Man kan också hoppa över en post vid inläsningen med ett tomt format: READ (5, 100) 100 FORMAT () För att läsa och skriva på andra enheter än en skärmterminal, används logiska enhetsnummer. I Fortran reserveras vanligen 5 för standard-in och 6 för standard-ut. För att läsa och skriva på skivfiler (t.ex.) kan man använda andra enhetsnummer. En skivfil öppnas i allmänhet för inmatning eller utskrift med en OPEN-sats. När man är färdig, stänger man den med en CLOSE-sats (observera, att huvudprogrammets END-sats också automatiskt stänger alla öppna filer). En OPEN-sats kan t.ex. se ut så här: OPEN (10, FILE= fil.dat, STATUS= NEW ). Denna sats kommer att öppna en skivfil i enhet 10 med namnet fil.dat, som inte existerar förut (om den existerar, använder man specifikationen STATUS= OLD ). Om man använder parametern STATUS= SCRATCH kommer filen att strykas, då programmet avslutas. OPEN-satsen innehåller som vi ser en serie specifikationer, åtskiljda av kommatecken (observera apostroferna, som omger namnet som står efter likhetstecknet). En annan viktig specifikation i OPEN-satsen är ACCESS, som antingen kan vara ACCESS= SEQUENTIAL eller ACCESS= DIRECT. Denna specifikation anger filtypen. I det förra fallet är filen sekventiell, dvs den kan läsas bara i en riktning (utgångsantagandet ifall man inte anger filtypen). I det senare fallet kan den läsas i vilken riktning som helst (direktaccess). Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 3

Varje fil tänkes uppdelad på poster (eng. record ), som för textfiler kan tolkas som rader. Om filtypen tillåter direkt access, måste också storleken av varje post anges med specifikationen RECL=num, där num anger antalet bytes (t.ex. 80). CLOSE-satsen som stänger en fil, har också flere specifikationer, men vanligen används den i formen CLOSE (num) (eller CLOSE (UNIT = num)), där num anger enhetsnummern. En sats som är nyttig för sekventiella filer, är REWIND, som används för att börja behandla filen igen från början. Som ett exempel kan vi studera en del av ett program, som först skriver data på en fil, och sedan läser samma fil på nytt: OPEN (10, FILE= test.dat, STATUS= NEW ) WRITE (10, 10) x,y, (z(i), i=1,n) REWIND 10 READ (10,10) a,b, (c(k), k=1,n) 10 FORMAT (10F8.4) Observera, att data i en fil alltid läses på samma sätt som de skrivits! Istället för att skriva formaterade data, som i fallet ovan, kan man också skriva oformaterade data. Isåfall bör OPEN-satsen innehålla specifikationen FORM= UNFORMATTED, och formatnummern utelämnas då vid läsning och skrivning. I detta fall kommer data att skrivas i binär form, vilket leder till tätare packning (men gör det svårare att använda datafilen på en annan dator). Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 4

Som ett exempel skall vi studera ett program, som läser en fil, som skrivits oformaterat, och skriver ut formaterade data på en annan fil. PROGRAM bin2text! Program som konverterar en binär fil till text IMPLICIT NONE REAL :: x(100), y(100), a(100,100) INTEGER :: i,j,k,n OPEN (10, FILE= bin.dat, FORM= UNFORMATTED, STATUS= OLD ) READ (10) n READ (10) (x(i), i=1,n),(y(i), i=1,n) READ (10) ((a(i,j),j=1,n), i=1,n) CLOSE (10) OPEN (20, FILE= asc.dat, STATUS= NEW ) WRITE (20, *) Elementen i vektorn x: WRITE (20, 100) DO i=1,n,8 WRITE (20, 100) (x(j), j=i,min(i+7,n)) WRITE (20, (/A) ) Elementen i vektorn y: WRITE (20, 100) DO i=1,n,8 WRITE (20, 100) (y(j), j=i,min(i+7,n)) Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 5

WRITE (20, (/A) ) Elementen i matrisen A: DO i=1,n DO j=1,n,8 WRITE (20, 100) (a(i,k), k=j, min(j+7,n)) STOP 100 FORMAT (T1,8F9.4) END PROGRAM bin2text Som vi ser, kommer programmet att skriva (högst) åtta tal per rad (observera användningen av funktionen min!). Vid utskriften används implicerade DO-satser, som vi tidigare har nämnt. Formatbeteckningen (/A) leder till att texten föregås av en tom rad (anges av snedstrecket). Den binära filen bin.dat i ovanstående exempel skulle man t.ex. kunna alstra med programmet PROGRAM bintest! Program som genererar en binär testfil IMPLICIT NONE REAL :: x(100), y(100), a(100,100) INTEGER :: n, i, j! Läs in en lämplig dimension (högst 100): Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 6

DO PRINT *, Matrisdimensionen (högst 100): READ *,n IF (n > 0.and. n <= 100) EXIT! Konstruera matriserna: DO i=1,n x(i) = 10.*i y(i) = i/10. DO j=1,n a(i,j) = i*j! Öppna filen och skriv ut matriserna OPEN (10, FILE= bin.dat, FORM= UNFORMATTED, STATUS= NEW ) WRITE (10) n WRITE (10) (x(i), i=1,n), (y(i), i=1,n) WRITE (10) ((a(i,j), j=1,n), i=1,n) STOP END PROGRAM bintest Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 7

Matrisdimensionen testas här med en öppen DO-konstruktion för att kontrollera, att den håller sig innanför stipulerade gränser. Med n = 5 ser utskriften från bin2text ut på följande sätt: Elementen i vektorn x: 10.0000 20.0000 30.0000 40.0000 50.0000 Elementen i vektorn y: 0.1000 0.2000 0.3000 0.4000 0.5000 Elementen i matrisen A: 1.0000 2.0000 3.0000 4.0000 5.0000 2.0000 4.0000 6.0000 8.0000 10.0000 3.0000 6.0000 9.0000 12.0000 15.0000 4.0000 8.0000 12.0000 16.0000 20.0000 5.0000 10.0000 15.0000 20.0000 25.0000 Vi har tidigare beskrivit hur man öppnar filer för in- och utmatning i Fortran. Vi skall nu diskutera ytterligare några parametrar, som ingår i OPEN-satsen. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 8

En av dem är IOSTAT, som anger en heltalsvariabel, vars värde är lika med 0, om filen öppnats utan problem, men annars olika 0. Ett exempel på användningen ges av följande programfragment, som frågar efter namnet på en existerande fil, som öppnas. Ifall något problem uppstår, ges ett felmeddelande. PRINT *, "Ange filnamnet" READ (A), filnamn OPEN (UNIT=1, FILE=filnamn,STATUS="OLD",IOSTAT=ios) IF (ios /= 0) THEN PRINT *, "Kan inte öppna ",filnamn... END IF Parametern IOSTAT kan också användas i in- och utmatningssatser. Värdet 0 anger då att satsen utförts utan problem, medan ett positivt värde anger att ett fel uppstått. Vid in- och utmatning anger ett negativt värde (oftast) att filen tagit slut. Filens slut anges av ett särskilt sluttecken i filen, som skrivs med satsen ENDFILE n, där n anger enhetens nummer. Detta kan t.ex. utnyttjas om man vill lägga till data i slutet av en sekventiell fil, såsom visas av följande exempel: Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 9

...! Hoppa till slutet DO READ (UNIT=1, IOSTAT=ios) z IF (ios<0) EXIT! negativ status betyder slutet! Gå ett steg tillbaka BACKSPACE 1! Skriv ny information WRITE (1) x... Man kan också lägga till data i slutet av en fil genom att öppna den med parametern POSITION = APPEND. BACKSPACE-satsen behövs alltid, om filen innehåller ett sluttecken (beror på systemet). Ett dylikt sluttecken kan också explicit skrivas in i filen med ENDFILE-satsen. Istället för IOSTAT kan man i I/O-satser också använda parametern END = num, som överflyttar kontrollen till en instruktion med satsnummern num, ifall filen tar slut. Användningen av IOSTAT rekommenderas dock, eftersom den möjliggör bättre kontroll över vad som verkligen händer. Ytterligare exempel på filhantering ges i följande program, som söker upp ett namn i en fil som innehåller t.ex. namn på användare och användarkoder, och skriver ut användarkoden, ifall namnet kan hittas (för att avsluta sökningen, används * *). Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 10

PROGRAM search! Program som söker upp användarnamn i en sekventiell fil IMPLICIT NONE CHARACTER(LEN=20) :: fil_namn, f_namn, t_namn, f_n, t_n, a_n INTEGER :: ios LOGICAL :: funnet! Ange filnamn och öppna filen: DO PRINT *, "Ange filnamn:" READ *, fil_namn OPEN (UNIT=1, FILE=fil_namn, STATUS="OLD", IOSTAT=ios) IF (ios == 0) EXIT PRINT *, "Fel på filen!"! Ange förnamn och tillnamn DO funnet =.FALSE. PRINT *, "Förnamn och tillnamn:" READ *, f_namn, t_namn IF (f_namn == "*".AND. t_namn == "*") EXIT REWIND (1)! Sök upp den rätta posten DO READ (UNIT=1, FMT=*, IOSTAT=ios) f_n, t_n, a_n Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 11

IF (ios<0) THEN! Filen tog slut EXIT ELSE IF (ios>0) THEN! Fel i filen PRINT ("Fel nr ",I3," vid läsning av fil ",A),ios,fil_namn STOP END IF IF (f_namn == f_n.and. t_namn == t_n) THEN PRINT *, "Användarkoden = ",a_n funnet =.TRUE. END IF IF (.NOT. funnet) PRINT *, "Namnet ej funnet!" STOP END PROGRAM search Vid in- och utmatning i Fortran brukar satserna READ, WRITE och PRINT vanligen inleda behandlingen av en ny post. Det finns fall då man skulle vilja läsa endast en del av en post, och resten senare. Detta, som inte var möjligt med FORTRAN 77, kan göras med Fortran 90. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 12

Metoden kallas icke-framskridande ( non-advancing ) in- och utmatning, och kan användas endast vid formaterad behandling av sekventiella filer. I detta fall behöver man inte behandla en hel post såsom fallet är vid normal filhantering. Dessutom får man reda på antalet tecken som posten innehåller, samt underrättas om filen tagit slut under läsningen. Icke-framskridande in- och utmatning anges med parametern ADVANCE i en READ eller WRITE sats, som har formen ADVANCE = "YES" eller ADVANCE = "NO". I det förstnämnda fallet används den normala, framskridande metoden, medan man i det senare fallet använder den nya, icke-framskridande metoden. Om ADVANCE ="NO" ingår i en READ-sats, finns det tre möjligheter: 1) Posten lästes inte i sin helhet, och det uppstod inga fel under läsningen. I detta fall kommer nästa READ-sats att fortsätta med behandlingen av samma post. 2) Om posten blivit läst förbi sluttecknet (vilket kan testas med IOSTAT), kommer positionen i filen att vara omedelbart efter ifrågavarande post. Detta uppfattas dock inte som ett feltillstånd. 3) Om något fel inträffade under läsningen (t.ex. filen tog slut) kommer positionen i filen att vara omedelbart efter senast lästa post. För att få reda på hur många tecken som blivit lästa, används parametern SIZE. Sålunda kommer t.ex. den icke-framskridande READ-satsen Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 13

READ (UNIT=1, FMT=100, ADVANCE="NO", SIZE =nc, & IOSTAT=ios) x,y,z att lagra antalet lästa tecken i variabeln nc, och heltalsvariabeln ios kommer att ange hur läsningen har lyckats. Vid icke-framskridande utmatning finns det bara två möjligheter, antingen uppstod inga fel, och då kommer nästa WRITE-sats att fortsätta med samma post, eller också uppstod det något fel, och positionen i filen kommer att vara efter senast skrivna post. De flesta filer, som vi hittills haft att göra med, har varit sekventiella, dvs de kan läsas och skrivas bara i en riktning. Men man kan också behandla posterna i en fil i en godtycklig ordning, om man öppnar filen med parametern ACCESS="DIRECT". I detta fall måste alla poster i filen ha samma längd, vilket anges genom specifikationen RECL =n, där n är ett heltal, som anger den konstanta postlängden. Posterna i en direktaccess-fil uppfattas vara numrerade. Sålunda kan man t.ex. skriva post 100 oformaterat med satsen WRITE (UNIT=1, REC=100) x,y,z. En formaterad utskrift av formen WRITE (UNIT=1, REC=100, FMT= (10I5) ) (m(i), i=1,100) anger att tio poster kommer att skrivas, utgående från post 100. Observera också då man öppnar en fil för direkt access, att parametern FORM = UNFORMATTED är underförstådd. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 14

Posterna i en fil med direkt access kan skrivas i vilken ordning som helst. En post som har blivit skriven, kan skrivas över på nytt, men inte strykas. Om postens längd är kortare än specifikationen RECL, kommer den att fyllas ut till rätt längd. Ett exempel på ett program som använder direkt access för att läsa en fil, skriven med direkt access, visas nedan. PROGRAM direct! Programmet testar direkt access IMPLICIT NONE CHARACTER :: post*80, fil_namn*30 INTEGER :: ios, post_nr! Ange filnamn och öppna filen: DO PRINT *, "Ange filnamn:" READ *, fil_namn OPEN (UNIT=1, FILE=fil_namn, ACCESS="DIRECT", & FORM="FORMATTED", STATUS="OLD", RECL=50, IOSTAT=ios) IF (ios == 0) EXIT PRINT *, "Fel på filen!"! Ange postnummer DO PRINT *, Ange postnummer (0 avslutar): Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 15

READ *, post_nr IF (post_nr <= 0) EXIT! Sök upp posten, och skriv ut den READ (UNIT=1, FMT = (A), REC = post_nr, IOSTAT = ios) IF (ios == 0) THEN PRINT *, post ELSE PRINT *, "Läsfel!" END IF PRINT *, "Filen behandlad" STOP END PROGRAM direct post Om filen inte kunde öppnas, kommer heltalsvariabeln ios att få ett värde olika noll. Detta sker både ifall filnamnet är orätt skrivet, eller filen har fel format (t.ex. variabel postlängd, etc.). Om det angivna postnumret inte är positivt, avbryts programmet, medan postnumret i annat fall anges på nytt. Om man anger ett större postnummer än vad som finns i filen, kommer heltalsvariabeln ios att få ett värde olika noll, vilket anges som läsfel. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 16

Filer av det slag som vi tillsvidare diskuterat, brukar också kallas yttre filer för att skilja dem från s.k. inre filer, som egentligen inte är några filer, men beter sig som sådana. En inre fil är egentligen bara ett sätt att konvertera mellan olika format. En dylik fil är vanligen en variabel av typ CHARACTER. Bäst förklarar man användningen med ett exempel. CHARACTER (LEN=50) :: rad WRITE (UNIT=rad, FMT= (2F10.5,3I10) ) x,y,i,j,k READ (UNIT=rad, FMT= (2(F8.3,2X),3(I8,2X)) ) x,y,i,j,k WRITE-satsen kommer här att alstra en teckensträng i variabeln rad som består av värdena av de reella variablerna x och y med fem decimaler och tio tecken vardera, samt heltalsvariablerna i, j och k också med tio tecken var. Dessa variabler matas in i samma teckensträng och förkortas till åtta tecken var. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 17

2.9. Noggrannhet och precision vid numeriska beräkningar Nogrannhet i datorframställningen av ett flyttal bestäms av antalet bitar i mantissan, och vilka tal som kan framställas på detta sätt bestäms av vilka värden exponenten kan anta. Detta beror givetvis på datorns ordlängd, vilket ställer till med problem då man överför program mellan olika datorer. För att avhjälpa detta, har man infört parametriserade variabler i Fortran 90 vilket gör det möjligt att kontrollera precisionen och exponentens räckvidd. Parametriseringen sker med en särskild parameter KIND. Vi skall belysa detta med några exempel: REAL :: x, y, z REAL, DIMENSION(100) :: a REAL(KIND=4) :: b, c REAL(KIND=2) :: v(5) Variablerna x, y, z och vektorn a är alla vanliga variabler av typ REAL, medan b och c har KIND typ 4 och vektorn v har KIND typ 2. För att ta reda på KIND-typen, kan man använda en inbyggd funktion KIND. Sålunda kommer t.ex. satsen i = KIND(b), om b deklarerats som ovan, att ge värdet 4 åt variabeln i. Det är inte nödvändigt att utsätta parameternamnet KIND i en deklaration, det räcker att skriva t.ex. REAL(4), men det blir tydligare om man använder den fullständigare formen REAL(KIND=4). Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 18

I allmänhet är KIND-typerna datorberoende, men det finns en möjlighet i Fortran 90 att konstruera KINDparametrar, som är helt datoroberoende. Detta sker med den inbyggda funktionen SELECTED REAL KIND, som kan ha två heltaliga argument, P och R (det finns även SELECTED INT KIND). Det förstnämnda argumentet P anger minimiantalet decimaler som behövs, och det andra argumentet R anger den minsta räckvidden för exponenten som behövs. Om man t.ex. deklarerar en variabel med satsen REAL(KIND=SELECTED REAL KIND (P=7,R=30)) :: a, så betyder det att man för att framställa a behöver minst 7 decimaler och att exponentens räckvidd bör vara minst 30. Om samma noggrannhet används i flera deklarationer, lönar det sig att definiera en särskild konstant för KIND-parametern, t.ex. på följande sätt: INTEGER, PARAMETER :: real_7_30 = SELECTED_REAL_KIND(P=7,R=30)... REAL(KIND=real_7_30) :: a... I de flesta datorer är det möjligt att lagra flyttal i enkel eller dubbel precision, och de har hårdvara för att utföra aritmetiska operationer med dem. Om datorn räknar med sex signifikanta siffor och har en exponenträckvidd av 40, kommer den i ovanstående fall att räkna med dubbel precisions noggrannhet, men om ordlängden å andra sidan är så lång, att enkel precision räcker till för att framställa tal med 15 signifikanta siffror, och exponentens räckvidd är 300, så räcker enkel precision till i detta fall. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 19

För att bättre inse betydelsen av precision vid numeriska beräkningar skall vi studera ett program, som beräknar uttrycket (1 2 2 3... 2n 1 ) 2 ( ) 2 3 2n 1 2... 2n 2n 1 för olika värden av n, och med olika stor precision (som man får om man ändrar argumentet P i SELECTED REAL KIND: PROGRAM prec_test IMPLICIT NONE INTEGER, PARAMETER :: real6 = SELECTED_REAL_KIND(P=6,R=32) REAL(KIND=real6) :: x, p, q, s INTEGER :: k, n DO PRINT *, Ge värdet av n= READ *,n IF (n <= 0) EXIT x = 1. p = 1. DO k=1,2*n-1 x = REAL(k) p = (x/(x+1.))*p x = 1. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 20

q = 1. DO k=1,2*n-1 x = REAL(k) q = ((x+1.)/x)*q s = SQRT(p*p)*q PRINT *, s STOP END PROGRAM prec_test Det matematiskt korrekta resultatet är 1, men avrundningsfel kommer att leda till fel, som är särskilt markanta vid låg precision (t.ex. 6 decimaler), vilket framgår av nedanstående exempel: OUTO...ADB_KURS>r prec_test2 Ge värdet av n= 1000 1.000008 Ge värdet av n= 100000 1.000280 Ge värdet av n= 1000000 1.004621 Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 21

Om man ökar precisionen (t.ex. till 14 decimaler), minskar avvikelsen betydligt, vilket man ser genom att testköra en modifikation av programmet ovan: OUTO...ADB_KURS>r prec_test3 Ge värdet av n= 1000 0.999999999999998 Ge värdet av n= 100000 0.999999999999947 Ge värdet av n= 1000000 1.00000000000001 Vi skall också studera hur KIND typerna kan användas för ange precision i numeriska metoder. En av de enklaste metoderna att numeriskt beräkna en rot till en ekvation brukar kallas funktionsiteration. Om man på något sätt kan skriva ekvationen f(x) = 0 i formen x = g(x), så kan man iterera fram en rot genom utgå från en approximation till roten, substituera den i högra membrum samt räkna ut en ny approximation till roten. Detta betyder att man beräknar roten genom successiva approximationer: x n+1 = g(x n ), n = 0, 1, 2,.... Beräkningen avbryts, då skillnaden mellan två på varandra följande approximationer är mindre än en given toleransgräns: x n+1 x n < ɛ. Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 22

Metoden har tillämpats i följande program, som beräknar den reella roten till ekvationen x 3 2x 5 = 0. Denna ekvation, som studerades redan av Newton 1669, kan skrivas i formen x = (2x + 5) 1/3, vilket gör det möjligt att tillämpa funktionsiteration. MODULE precision! Modul som anger variablernas precison IMPLICIT NONE INTEGER, PARAMETER :: r=selected_real_kind(p=14,r=30) END MODULE precision MODULE functions IMPLICIT NONE CONTAINS FUNCTION fn(x) USE precision IMPLICIT NONE REAL(KIND=r) :: fn REAL(KIND=r), INTENT(IN) :: x fn = (2._r*x + 5._r)**(1._r/3._r) RETURN END FUNCTION fn END MODULE functions PROGRAM fun_it! Program för iterativ rotbestämning: x = fn(x) USE precision Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 23

USE functions IMPLICIT NONE REAL(KIND=r) :: x, x1, dx INTEGER :: i, maxit PRINT *, "Ge en approximation till roten" READ *, x1 PRINT *, "Ge maximiantalet iterationer" READ *, maxit PRINT *, "Ge önskad precision" READ *, dx! Iterera: DO i=1,maxit x = fn(x1) IF (ABS(x-x1) < dx) EXIT x1 = x PRINT *, " x = ",x IF (i > maxit) PRINT *, "Proceduren har inte konvergerat" PRINT *, "Antal iterationer: ",i PRINT *, " x = ",x STOP END PROGRAM fun_it Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 24

I detta program, liksom i det föregående programmet, användes 14 decimalers precision, som definierats i en särskild modul, kallad precision. Variabler med denna precision har deklarerats som REAL(KIND=r). På ett liknande sätt har också konstanter angetts med samma precision, t.ex. 2. r. Konvergensen är rätt snabb, med utgångsvärdet x = 2 fås ett resultat med tio korrekta decimaler efter 12 iterationer, och med utgångsvärdet x = 100 efter 15 iterationer: Ge en approximation till roten 2 Ge maximiantalet iterationer 30 Ge önskad precision 1.E-10 x = 2.08008382305190 x = 2.09235067779758 x = 2.09421699601252 x = 2.09450065219465 x = 2.09454375753281 x = 2.09455030780827 x = 2.09455130318276 x = 2.09455145443897 x = 2.09455147742373 x = 2.09455148091647 x = 2.09455148144722 Antal iterationer: 12 x = 2.09455148152787 Introduktion till vetenskapliga beräkningar II, Tom Sundius 2009 25