Ohjelmointi ja numeeriset menetelmät, luento 2

Yhteenveto F90:n perusominisaisuuksista (tähän mennessä)


Merkkivalikoima

Kirjaimet: a-z, A-Z
Numerot: 0-9
Erikoismerkit: , . ; : % ! + - * / ( ) = ' " & < > ? $ _

Merkkijonoissa ja kommenteissa voi yleensä käyttää muitakin merkkejä.


Ohjelman ulkoasu

Pienillä ja isoilla kirjaimilla ei eroa.

Lause päättyy rivin loppuun, ellei muuten osoiteta.

Rivin lopussa oleva &-merkki ilmoittaa, että lause jatkuu seuraavalla rivillä. Lauseen maksimipituus 40 riviä.

Rivin loppu huutomerkistä eteenpäin on kommenttia, joka ei vaikuta ohjelman toimintaan.


Yksinkertaiset muuttujat

Muuttujan nimi korkeintaan 31 merkkiä, nimessä voi käyttää kirjaimia, numeroita ja alaviivaa (_). Nimen alettava kirjaimella. Yksinkertaiset tyypit:
        integer
        real
        logical  (arvo .true. tai .false. )
        complex
        double precision
        character
Muuttuja voidaan alustaa määrittelyn yhteydessä:
        integer :: n=0
        real :: x=0.1
Vakiot:
        integer, parameter :: maxn=1000
        real, parameter :: pi=3.141592654


Muuttujan tarkkuus

F90:ssä haluttu esitystarkkuus määriteltävissä laitteistosta riippumattomalla tavalla. Mutta: toteutetaan vain muutaman erilaisen muuttujatyypin avulla, mielivaltaisen suurta tarkkuutta ei ole käytettävissä.

Määritellään kind-määreellä:

        integer, (kind=1) :: n
Kind-määreen arvot toteutuskohtaisia. Siis ei käytetä näin, vaan haetaan sopiva arvo systeemifunktiolla:
        integer, (kind=selected_int_kind(5)) :: n
Nyt muuttujalle n varataan tila, johon mahtuu ainakin 5 numeron kokonaisluku.
        real (kind=selected_real_kind(5)) :: a, b
        real, (kind=selected_real_kind(10,50)) :: x
Muuttujien a ja b tarkkuus 5 merkitsevää numeroa, muuttujassa x 10 merkitsevää numeroa ja eksponentti välillä [-50, 50].
        integer, parameter :: short=selected_int_kind(4), &
                              long=selected_int_kind(7), &
                              longreal=selected_int_kind(10, 100)
        integer (kind=short) :: i,j
        integer (kind=long) :: isoluku
        real (kind=longreal) :: big
Vakiot:

Kokonaisluvut

        123
        123_short
        1234567_long
Reaaliluvut
        1.5
        -1.5
        1.5E10
        1.5E-10
        1.5_longreal
        1.5E-10_longreal
Kompleksiluvut
        complex z
        z = (1.0, -1.0)   ! z=1-i


Merkkijonot

        program koe
          character a='A'
          character (len=3) :: b='xyz'
          character (len=6) :: c,d,e
          c = b//a//'qq'   ! katenaatio
          d = c
          d(1:2)='--'
          e='X'
          write(6,*) a,b,c,d,e
       end program
Ohjelman tulostus
        A
        xyz
        xyzAqq
        --zAqq
        X     


Sijoitusoperaattori =

        i=100
        x=1.5
Ensin lasketaan koko oikea puoli ja muunnetaan ennen sijoitusta vasemman puolen mukaiseksi.


Lausekkeet

        1.0+2.0*y/z**2-3.5*sqrt(y+x)
Normaali assosiatiivisuus:
- ensin funktiokutsut (sqrt, sin, ...)
- sitten ** (potenssiinkorotus) oikealta vasemmalle
- sitten * ja / vasemmalta oikealle
- lopuksi + ja - vasemmalta oikealle
- järjestystä voidaan muuttaa suluilla

Kokonaislukujen jakolaskun tulos on kokonaisluku (osamäärän kokonaisosa)


Varusfunktiot (intrinsic functions)

        sin(x), cos(x), tan(x)
        asin(x), acos(x), atan(x), atan2(y,x)
        sinh(x), cosh(x), tanh(x)
        exp(x), log(x), log10(x), sqrt(x)
        min(x, y, ...), max(x, y, ...)
        abs(x)


Loogiset lausekkeet

Vertailuoperaattorit:
        ==    .eq.
        /=    .ne.
        <     .lt.
        <=    .le.
        >     .gt.
        >=    .ge.
Loogiset vakiot:
 
        .true.  .false.
Loogiset operaattorit:
        .and.   
        .or.    
        .not.   
X.and.Y on tosi, jos ja vain jos X==.true. ja Y==.true..

X.or.Y on tosi, jos X==.true. tai Y==.true. tai molemmat ovat tosia.

.not.X on tosi, jos X==.false.


Peruskontrollirakenteet: Peräkkäisyys

Tavallisesti kukin lause omalla rivillään.

Samalla rivillä voi olla useita lauseita, jotka erotetaan puolipisteellä.


Peruskontrollirakenteet: Valinta

Yksi vaihtoehto
       if (x > 0.0) y = 1/x

       if (x > 0.0 .and. x < 100.0) y=exp(x)

       if (x > 0.0) then
          y=1/x
          z=log(x)
       end if 

Kaksi vaihtoehtoa

        if (x > 0.0) then
           y=1/x
        else
           y=0.0
        end if

Useampia vaihtoehtoja

        if (x > 0.0) then
           y=log(x)
        else if (x < 0.0) then
           y=-log(abs(x))
        else
           y=0.0
        end if


Peruskontrollirakenteet: Toisto

Kiinteä kierrosmäärä
        sum=0.0
        do i=1,100
           sum=sum+i
        end do
        sum=0.0
        do i=0,100,2  ! parillisten lukujen summa
           sum=sum+i
        end do

Testataan silmukan suoritusehtoa ennen silmukan suoritusta. Jo ehto on heti epätosi, silmukkaa ei suoriteta kertaakaan.

        sum=0.0 ; term = 1.0
        do while (term > 1.0E-5)
           sum=sum+term
           term=term*0.1
        end do
Testataan lopetusehtoa silmukan keskellä (n+1/2 kierroksen silmukka):
        sum=0.0 ; i = 1
        do
           sum=sum+1.0/i
           if (sum > 10) exit
           i=i+1
        end do
        x0 = 0.5
        n=0
        do 
          x1=(1.0+x0)**0.2
          if (abs(x1-x0) < 0.0001) exit
          n=n+1
          if (n > 100) exit
          x0=x1
        end do

Syöttö ja tulostus

        read (laitenumero, formaatti) muuttujaluettelo
        write (laitenumero, formaatti) muuttujaluettelo

        open (laitenumero, tiedoston attribuutit)
        close (laitenumero)
Kullakin tiedostolla on yksikäsitteinen laitenumero (LUN, logical unit number).

Perinteisesti 5=kortinlukija (nykyisin yleensä pääte), 6=rivikirjoitin (se sama pääte).

Formaatti on merkkijono, joka määrittelee, miten tulostus muotoillaan. Vapaan formaatin merkki on *.

Vapaamuotoinen tulostus:

        i=10; x(i)=1.2345
        write (6,*) i, x(i)

     10 1.23450005
Muotoiltu tulostus
        write (6, '(I3,F5.2)') i,x(i)
Muotoimet:

In kokonaisluku n numerolla

Fn.d reaaliluku, kaikkiaan n merkkiä, d desimaalia

En.d tulostus eksponenttimuodossa

Jos luku ei mahdu kenttään, tulostetaan n tähteä; jos luku ei täytä koko kenttää, se tasataan oikeaan reunaan

An n merkin merkkijono; jos tulostettava merkkijono ei mahdu kenttään, tulostetaan vain n ensimmäistä merkkiä; jos merkkijono on lyhempi kuin n, se tasataan kentän oikeaan reunaan

nX ohitetaan n merkkiä

Tn (tabulaattori) siirrytään sarakkeelle n

/ rivinvaihto

Automaattinen rivinvaihto jokaisen writen jälkeen.

Jos tulostettavia on enemmän kuin muotoimia, tehdään rivinvaihto ja aloitetaan muotoinluettelo uudelleen alusta.

        real x(10)
        write(6,'(F5.2)') x    ! tulostaa 10 rivia
        write(6,'(10F5.2)') x  ! tulostaa samalle riville
        write(6,'(30F5.2)') x  ! tulostaa vain 10 lukua
        write(6,'(3F5.2)') x   ! tulostaa 4 riviä (3+3+3+1 lukua)

Muotoin on vain merkkijono, jota ei tarkisteta käännösaikana. Suoritus voi kaatua ajoaikana, jos muotoin ei vastaa tulostettavan luvun tyyppiä.

read: samat muotoimet kuin tulostuksessa.

Vapaamuotoinen syöttö: muuttujat annetaan pilkuilla erotettuina:

        real x
        integer n
        read(5,*) x,n 

     1.5,20
Muotoiltu syöttö (lähinnä tiedostojen lukemiseen):
        read(5,'(F4.1I2)') x,n 
     ! 1.520
     !1.5 20
     !  1520
Kaikki antavat tuloksen x=1.5, n=20. Viimeisessä tapauksessa luetaan 4 merkin kenttä ( 15), josta yksi merkki tulkitaan desimaaliosaksi.


Ohjelmatiedostot

Tiedostossa voi olla:

1) Pääohjelma + mahdollisia sisäisiä proseduureja

2) Yksi tai useampia ulkoisia proseduureja

3) Moduuli, joka voi sisältää muuttujien määrittelyjä ja omia sisäisiä proseduurejaan


Proseduurit

Proseduuri voi olla

1) Funktio, joka palauttaa jonkin arvon:

        program ...

        y = sinc(1.5)

        contains

        real function sinc(x)
          real x
          sinc = sin(x)/x
        end function 

        end program

2) Aliohjelma, jonka toiminta perustuu sivuvaikutuksiin: aliohjelma muuttaa parametrejaan tai globaaleja muuttujia, tulostaa jotakin jne.

Aliohjelmaa kutsutaan call-lauseella.

        program ...

        call store (n)

        contains
        subroutine store(n)
          integer n
          write(6,*) n
          return
        end subroutine

        end program


Proseduurin paikalliset muuttujat

        real, save :: x
Jos usein kutsuttavassa aliohjelmassa suuria dynaamisesti varattavia taulukoita, toiminta hidastuu


Globaalit muuttujat

     program esimerkki
     real x, y, z, u
     x=0.1
     y=1.0
     z=1.0
     u=f(x)     
     write (*,'(4F10.4)') x,y,z,u

     contains

     real function f(x)
        real x, y
        y=x**2
        z=sin(x)
        f=z * y
     end function

     end program esimerkki
Tulostus:
    0.1000    1.0000    0.0998    0.0010
Pääohjelman muuttujat x, y, z, u ovat globaaleja.

Funktion y on paikallinen, joten sen muuttaminen ei vaikuta kutsuvan ohjelman muuttujaan y.

Funktion sisällä ei ole määritelty muuttujaa z, joten se viittaa globaaliin muuttujaan z. Tämä on funktion sivuvaikutus, eikä välttämättä toivottu.


Proseduurien parametrit (argumentit)


Sivuvaikutukset

    x=1
    call sub(x)
    write(6,*) x   ! 2
    call sub(1)    ! ??
    call sub(x+y)  ! ??

    subroutine sub(x)
    real x
    x=x+1
    end
    subroutine sub (x)
    real, intent(in) :: x
    x=x+1      ! kielletty!
    end

Intent-attribuutti

out: todellinen argumentti saa olla vain muuttuja; aliohjelman on annettava sille arvo, mutta muuttujaa ei saa käyttää esim. sijoituslauseen oikealla puolella.

inout: ei käyttörajoituksia, mutta todellisen argumentin oltava muuttuja.

Intent-attribuutti puuttuu: ei mitään rajoituksia.


Positionaalinen parametri: paikka parametrilistassa mr, mit muodollista parametria todellinen parametri vastaa.

Avainsanaparametri (keyword): jrjestys vapaa, parametri tunnistetaan nimen perusteella.

        subroutine huu(x,y,z)
        real x, y, z
        ...
        end
Kutsu voi olla
        real a, b, c
        call huu(a, b, c)
        call huu(a, z=b, y=1.0)
        call huu(z=b, x=a, y=c)
        call huu(x=a, b, c)       ! kielletty
Valinnainen parametri voi puuttua:
        subroutine haa(x,y,z)
        real x
        real, optional :: y,z
        real zz=42.0
        ..
        if (present(z)) zz=z 

        end
Sopii tilanteeseen, jossa muuttujalla yleensä järkevä oletusarvo.
        call haa(a)
        call haa(a, 0.1)
        call haa(a, b, c)
        call haa(a, z=1.5)
        call haa(x=a, z=1.5, y=1.0)
argumentti voi olla muuttuja, vakio tai lauseke.

Funktiot

Funktio palauttaa laskemansa arvon.

Funktiolla voi olla myös sivuvaikutuksia; niitä tulisi välttää.

Funktiolle on aina määriteltävä tyyppi.

        real function sinc(x)
        real, intent(in) :: x
        if (abs(x) < epsilon)
           sinc=1.0
        else
           sinc = sin(x)/x
        endif
        end function
Funktion arvo voi olla mikä tahansa muuttujatyyppi
        real x(3),y(3)
        x(:) = (/ 1, 2, 3 /)
        y=inv(x,3)

        ...

        function inv(x,n) 
          real, dimension(:), intent(in) :: x
          real, dimension(size(x)) :: inv
          integer n
          inv=x(n:1:-1)
        end

Funktio voi olla rekursiivinen:

        recursive function fibonacci(n) result(f)
        integer :: f
        integer, intent(in) :: n
        if (n<=2) then
           f=1
        else
           f=fibonacci(n-2)+fibonacci(n-1)
        endif
        end
Melko vähän käyttä numeerisissa tehtävissä.

Sopii esimerkiksi puiden ksittelyyn:

        program tree
        integer, parameter :: n=5
        integer left(n), right(n), data(n)
        left(:)  = (/  2,  4,  5,  0,  0 /)
        right(:) = (/  3,  0,  0,  0,  0 /)
        data(:)  = (/ 10, 20, 30, 40, 50 /)
        writetree (1)

        contains
        recursive subroutine writetree(n)
          integer n
          if (left(n)  > 0) writetree(left(n))
          write (6,*) data(n)
          if (right(n)  > 0) writetree(right(n))
        end
        end program

Moduulit

Kirjoitetaan proseduurit moduuliksi:
        module funcs
        contains
        real function sinc(x)
          ...
        end function sinc
        ...
        end module funcs
Moduuli käännetään erikseen ja otetaan käyttöön use-lauseella:
        program koe
        use funcs
        ...
        u=sinc(x)
        ...
        end program
Käännös esimerkiksi
  f95 -c funcs.f90
  ...
  f95 koe.f90 funcs.o


Ohjelmointityylistä

Strukturoitu ohjelmointi


Top down -menetelmä

  1. Määrittele tarkasti, mitä tietoja ohjelma saa ja mitä sen täytyy niille tehdä.
  2. Jos tehtävä on riittävän yksinkertainen, kirjoita sen suorittava ohjelmakoodi.
  3. Muuten jaa tehtävä pienempiin osiin ja määrittele tarkasti kunkin osan tehtävä ja liitäntä muuhun ohjelmaan.
  4. Suorita vaiheet 1-4 erikseen kullekin osatehtävälle.


Hyvän aliohjelman/funktion ominaisuuksia

Sisäinen lujuus:
Suorittaa yhden selvästi määritellyn tehtävän.
Tehtävä ei välttämättä yksinkertainen, mutta määriteltävissä yksinkertaisella tavalla.

Ohjelman paloittelu toiston välttämiseksi tai aliohjelmien koon pitämiseksi pienenä voi johtaa huonoon lujuuteen.

Ulkoiset kytkennät:
Mitä enemmän aliohjelma riippuu globaaleista muuttujista ja muista aliohjelmista sitä vaikeampi ohjelmaa on muuttaa.

Ideaalitilanne on, että kaikki tieto välitetään parametreina (vrt. sin, sqrt).

Taulukot

Yksiulotteisen taulukon määrittely:
        real x(3)
        real, dimension(3) :: a,b,c
        real, (kind=selected_int_kind(8)), dimension(0:5) :: z
Indeksin alarajan oletusarvo on 1. Voidaan muuttaa määrittelyssä:
        real x(0:10)
        real, dimension(-10:10) :: y
Myös taulukko voidaan alustaa määrittelyn yhteydessä:
        real, dimension(3) :: x = (/ 0.0, 0.5, 1.0 /)
        real, dimension(-10:10) :: y = 0.0
Monet operaatiot voivat kohdistua kokonaisiin taulukoihin:
       a=0.0
       a(1)=1.0
       a=b+c
       a=a+1
       a=sqrt(b)

Taulukon indeksinä voi olla myös kokonaislukutaulukko:

        integer, dimension(3) :: ind = (/ 4, 1, 3 /)
        integer, dimension(5) :: x = (/ 0, 2, 5, 1, 3 /)
       
        write(*,*) x(ind)


   1 0 5


Yksinkertainen lajittelu:
        real, dimension (n) :: x
        real :: tmp
        integer :: i,j

        do i=1,n-1
           do j=i+1,n
              if (x(j) < x(i)) then
                 tmp=x(i) ; x(i)=x(j) ; x(j)=tmp
              end if
           end do
        end fo
    
Ajankäyttö verrannollinen n2. Järkevää vain pienille taulukoille; Ei kannata suurille, kun on parempiakin menetelmiä.

Quicksort (rekursiivinen) yleensä nopea, mutta huono jo valmiiksi järjestyksessä olevalle aineistolle.

Kekolajittelu (heapsort) takaa, että aika korkeintaan n log n.


Kaksiulotteiset taulukot:
     real y(2,3)

!       y(1,1)   y(1,2)   y(1,3)
!       y(2,1)   y(2,2)   y(2,3)

      x = y(i, j)
      y(1, i-j) = z+0.5 * y(2,i)

      real, dimension(-1:1,0:100) :: z

!       z(-1,0)  z(-1,1)  ...  z(-1,100)
!       z( 0,0)  z( 0,1)  ...  z( 0,100)
!       z( 1,0)  z( 1,1)  ...  z( 1,100)
Useampiulotteiset samalla tavalla:
     real, dimension(2,2,2) :: u

!       u(1,1,1) u(1,1,2) ...  u(2,2,2)


Taulukoiden talletustapa poikkeaa muista kielistä:

Fortranissa 2-ulotteinen taulukko talletetaan sarakkeittain:

        real y(0:1,0:2)
       y(0,0)  y(0,1)   y(0,2)
       y(1,0)  y(1,1)   y(1,2)
Tämän alkiot ovat muistissa järjestyksessä
       y(0,0) y(1,0) y(0,1) y(1,1) y(0,2) y(1,2)
C:n taulukko y[2][3] talletetaan riveittäin
       y[0][0] y[0][1] y[0][2] y[1][0] y[1][1]  y[1][2] 
Asialla merkitystä tehokkuuden kannalta, jos käsiteltävä taulukko on hyvin suuri.


Taulukko-operaatiot

Laskutoimitus voi kohdistua kokonaiseen taulukkoon:
        integer, dimension (3) :: x, y, &
                               a = (/ 0, 1, 2 /), &
                               b = (/ 1, 3, 1 /)
        x = a+b     ! x = (/ 1, 4, 3 /)
        y = a*b     ! y = (/ 0, 3, 2 /)
        y = 2*b     ! y = (/ 2, 6, 2 /)
Operaattorit kohdistuvat vastinalkioihin; * ei ole matriisitulo.

Lausekkeessa esiintyvien taulukoiden oltava yhteensopivia.

Varusfunktiot voivat kohdistua kokonaiseen taulukkoon

        real, dimension (100) :: x, y
        x=0.1*(/ (i, i=1,100) /)
        y=sqrt(x)
Sijoituslauseen molemmilla puolilla oltava yhteensopivat taulukot.

Poikkeus: skalaari (yksinkertainen muuttuja) on yhteensopiva kaikkien taulukoiden kanssa:

        real, dimension (100) :: x, y
        real :: a

        y = 1.0
        x = y + a

Yhden alkion taulukko ei ole yksinkertainen muuttuja:
        real, dimension(1) :: x 
        real :: y 
        ...
        x = y   ! OK
        y = x   ! KIELLETTY


Taulukoihin liittyviä varusfunktioita
        real, dimension (100) :: x
        real ::  x0, x1
        integer, dimension(1):: k0, k1, i0, i1 ! HUOM, taulukkoja

        k0 = lbound(x)  ! indeksin alaraja
        k1 = ubound(x)  !          ylaraja
     
        x0 = minval(x)  ! pienin arvo
        x1 = maxval(x)  ! suurin arvo

        i0 = minloc(x)  ! pienimman arvon indeksi
        i1 = maxloc(x)  ! suurimman arvon indeksi

Toimivat myös useampiulotteisille taulukoille:
        real, dimension (2,3) :: x
        integer lo(2), hi(2), i1(2)
        x(1,:) = (/ 1, 2, 3 /)
        x(2,:) = (/ 2, 5, 1 /)

        lo=lbound(x)  !   lo = (/ 1, 1/)
        hi=ubound(x)  !   hi = (/ 2, 3/)
        i1=maxloc(x)  !   i1 = (/ 2, 2/)

Maxloc = suurimman alkion paikka taulukon alun suhteen:
        real, dimension (10:14) :: &
              x=(/ 0.0, 1.0, 5.0, 2.0, 1.0 /)
        integer, dimension(1):: l, n, i

        l = lbound(x)  !  l = (/ 10 /)
        n = ubound(x)  !  n = (/ 14 /)
        i = maxloc(x)  !  i = (/ 3 /)


Vektori- ja matriisioperaatioita:
        real, dimension (2,2) :: a, b, c
        real, dimension(3) :: &
                     v1 = (/ 1.0, 2.0, 3.0 /), &
                     v2 = (/ 2.0, 0.0, 1.0 /)
        real :: z, s, p
     
        a (1,:) = (/ 1.0, 1.0 /)
        a (2,:) = (/ 0.0, 1.0 /)

        b (1,:) = (/ 2.0, 0.0 /)
        b (2,:) = (/ 0.0, 1.0 /)

        s = sum(a)               ! alkioiden summa s = 3.0

        p = product(v1)          ! alkioiden tulo p = 3.0

        ! skalaaritulo 
        ! z = v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3) 
        ! ( = sum(v1*v2) )
        z = dot_product(v1, v2)  ! z = 5.0

        c = matmul (a, b)        ! matriisitulo
        ! c(1,1) = 2.0  c(1,2) = 1.0
        ! c(1,1) = 0.0  c(1,2) = 1.0

        c = matmul (b, a)       
        ! c(1,1) = 2.0  c(1,2) = 2.0
        ! c(1,1) = 0.0  c(1,2) = 1.0


Taulukkosektiot

Taulukon paikalla voi olla myös taulukon osa eli taulukkosektio.
        real, dimension(100) ::  a, b, c
        real, dimension(10, 100) ::  d
        integer :: i,j

        b(1:10) = c(51:60)

        a = d(1,:)

        c = a(100:1:-1)+b
     
        i=4 ; j=20
        d(1:3,1:5) = d(i:i+4:2, j:j+4)

        d(:,1) = d(5, 10:19)

Taulukkosektio voi olla mielivaltainen suorakulmainen, tasavälinen hila. Sijoituslauseen oikea puoli lasketaan aina kokonaan ennen sijoitusta.
        integer  a(3)
        a= (/ 0, 1, 2 /)
        a (2:3) = a (1:2)  ! a=(/ 0, 0, 1 /)
Tämä toimii eri tavalla kuin silmukka
        do i=2,3
           a(i) = a (i-1)
        end do
Taulukoiden käsittelyyn where-lause:
        where (x /= 0.0)  y=1/x


        where (x > 0.0)
           y = 1/x
           z = log(x)
        end where


        where (x > 0.0)
           y = 1/x
           z = log(x)
        elsewhere
           y = 0.0
           z = 0.0
        end where

Sama asia silmukalla:
         do i=1,n
            if (x(i) > 0.0) then
               y(i) = 1/x(i)
               z(i) = log(x(i))
            else
               y(i) = 0.0
               z(i) = 0.0
            end if
         end do


Muistiviittausten lokaalisuus

Virtuaalimuistikoneissa ohjelma paloitellaan tavallisesti kiinteän kokoisiksi sivuiksi, jotka talletetaan levylle. Keskusmuistiin ladataan sivuja sitä mukaa kuin niitä tarvitaan. Kun ohjelma viittaa sivulle, joka joudutaan lukemaan levyltä, tapahtuu sivunpuutoskeskeytys, jonka ajaksi ohjelman suoritus pysähtyy. Kun muisti täyttyy, poistetaan tavallisesti ne sivut, joihin viimeksi tehdystä viittauksesta on kulunut pisin aika.
        do i=1,100000
           x=a(i)
            ...
        end do
Useimmissa tapauksissa viitattu alkio on samalla sivulla kuin edellinenkin, joten tarvittava sivu on todennäköisesti jo valmiiksi muistissa.

Jos viittaukset kohdistuvat kaukana toisistaan oleviin alkioihin, ne osuvat usein eri sivuille. Mikäli kyseessä on suuri taulukko, aikaisemmin käytettyjä sivuja ehditään ehkä palauttaa levylle ennen kuin niihen viitataan uudestaan. Sivunpuutoskeskeytysten määrä voi kasvaa huomattavasti.

Muistiviittausten lokaalisuus: peräkkäiset viittaukset kohdistuvat aina lähellä toisiaan oleviin osoitteisiin.

Lokaalisuus parantaa muistin käytön tehokkuutta ja siitä on etua myös välimuistin (cache) käytön optimoinnissa.

Useampiulotteisten taulukoiden käsittely voi aiheuttaa ongelmia. Fortranissa taulukot talletetaan muista ohjelmointikielistä poiketen sarakkeittain eikä riveittäin.

        do i=1,1000
           do j=1,1000
              x=a(i,j)
              ...
           end do
        end do
Sisemmässä silmukassa haetaan taulukosta {\tt a} joka tuhannes alkio, jotka ovat kaikki eri sivuilla.

Ohjelma toimii paljon tehokkaammin, jos silmukoiden järjestys voidaan vaihtaa:

        do j=1,1000
           do i=1,1000
              x=a(i,j)
              ...
           end do
        end do