Symbolinen konekieli (assembler) vastaa yksikäsitteisesti konekielistä ohjelmaa, mutta on selväkielistä:
LD A ADD B MUL C STO AKorkean tason kieli vastaa matemaattista notaatiota tai luonnollista kieltä. (Fortran, Lisp, Cobol, Algol, Pascal, C, Java, ...)
A = (A+B)*CSovelluskehittimet tuottavat ohjelman kuvauksesta, joka kirjoitetaan hyvin tehtävänläheisellä kielellä.
Kääntäjä (compiler) on ohjelma, joka muuntaa korkean tason kielellä kirjoitetun ohjelman konekieliseksi, suoritettavaksi ohjelmaksi.
Kokonaisluku (integer) tavallisesti 2 tavua. Kokonaisluvun itseisarvo voi olla korkeintaan 215-1=32767.
Usein käytettävissä myös kaksoistarkkuuden kokonaisluku, 4 tavua, jolloin suurin esitettävissä oleva luku on 231-1=2147483647.
Reaaliluku (real) tavallisesti 4 tavua
- mantissan etumerkki
- mantissa normitettu välille 0.1 - 1
- eksponentti: etumerkki+itseisarvo tai 2:n komplementti
Esim. PC:n yksinkertaisen tarkkuuden reaaliluvun
mantissa on 23 bittiä. Desimaalipisteen jälkeinen
bitti on aina ykkönen, joten sitä ei tarvitse
tallettaa. Tarkkuus on 24 bittiä eli
log_10 224 \approx 7 desimaalia.
Eksponenttiosan pituus 8 bittiä. Eksponenttiosa
e = 127 (bias) + todellinen eksponentti; 1\le e
\le 254. Lukualue 2-126\approx 10-38 -
2128\approx 3x1038.
Kaksoistarkkuus: merkitsevien numeroiden määrä noin kaksinkertainen ja mahdollisesti myös lukualue laajempi. Esimerkiksi PC:n kaksoistarkkuuden muuttujien tarkkuus on noin 15 desimaalia ja lukualue noin 10-308 ... 10308.
Looginen muuttuja (logical) voi saada vain arvot tosi tai epätosi.
Osoitin (pointer)
- osoitetun muuttujan osoite muistissa + muuta tietoa
Taulukot (array)
Tietueet (record, structure)
S1 S2 S32 Valinta (1, 2 tai useita vaihtoehtoja)
if ehto then S1 if ehto then S1 else S2 case ehto { S1; S2; ... }3 Toisto
while ehto do S do S until ehto for i=1,n do SKaikki toistolauseet ovat erikoistapauksia n+1/2 kierroksen silmukasta
do { S1 if ehto exit S2 }Kaikki ohjelmointitehtävät voidaan toteuttaa em. rakenteilla.
Useissa kielissä lisäksi hyppykäsky (go to)
- yleensä tarpeeton
- sopii lähinnä poikkeustilanteisiin
- vaikeuttaa ohjelman luettavuutta
- kontrollireitit mutkistuvat
- osoitteesta ei näy, mistä siihen on tultu
GOTO 100 IF (I-J) 100,200,300
+ standardoitu -> hyvä siirrettävyys
+ saatavana hyviä aliohjelmakirjastoja (NaG yms.)
+ kääntäjät hyväksyvät myös vanhat ohjelmat, joita on liikkeellä paljon
- useimmat vanhoista ohjelmista hirveitä sekasotkuja
- kivikautisia sudenkuoppia, joita opittava varomaan
Esimerkki: Lähdekielinen ohjelma tiedostossa add.f90:
program add real x,y,z write(*,*) 'anna kaksi lukua' read (*,*) x,y z=x+y write(*,*) 'summa on',z end program addKäännös ja suoritus (esimerkiksi):
>f95 -o add add.f90 Compiling file add.f90. Compiling program unit add at line 1: > >./add anna kaksi lukua 1,3 summa on 4.00000000 >
Esimerkki: Yksinkertainen yhtälön ratkaisija
Kirjoitetaan yhtälö muotoon x=f(x). Esimerkiksi x5 - x - 1 = 0 ->
x = x5 - 1
tai
x = (1+x)0.2
program solve ! etsitaan yhtalon x**5-x-1=0 ! reaalijuuri real x0, x1 x0 = 0.5 ! arvataan alkuarvo x1=(1.0+x0)**0.2 ! iteroidaan, kunnes tulos ei muutu do while (x1.ne.x0) x0 = x1 x1 = (1.0+x0)**0.2 end do write (6, *) x1, x1**5-x1-1 end program solve
>f95 -o solve solve.f90 Compiling file solve.f90. Compiling program unit solve at line 1: >./solve 1.16730404 5.03132583E-07
Pienillä ja isoilla kirjaimilla ei eroa (paitsi mahdollisesti tiedostojen nimissä käyttöjärjestelmästä riippuen)
Lause päättyy rivin loppuun; erityistä erotinta ei tarvita.
Jos lause jatkuu useammalle riville, se on erikseen osoitettava. Rivin lopussa oleva &-merkki ilmoittaa, että lause jatkuu seuraavalla rivillä:
y = 1.0 + x + 0.5 * x**3 & + 1.0/6 * x**4Lauseen maksimipituus 40 riviä.
Rivin loppu huutomerkistä eteenpäin on kommenttia
- integer, jos ensimmäinen kirjain on I - N
- real muuten
Vaarallista! Väärin kirjoitettu muuttujan nimi tulkitaan vain eri muuttujaksi.
x0=1.0 x1=xO+1Määrittele kaikki muuttujat!
implicit noneYksinkertaiset tyypit:
integer real logical (arvo .true. tai .false. ) complex double precision characterVakiot:
integer, parameter :: maxn=1000 real, parameter :: pi=3.141592654maxn ja pi vakioita, joiden arvoja ohjelma ei saa muuttaa
i=100 x=1.5
1.0+2.0*y/z**2-3.5*(y+x)Normaali assosiatiivisuus:
Ensin lasketaan sijoitusoperaattorin = oikealla puolella oleva lauseke, se muunnetaan vasemmalla olevan muuttujan tyyppiseksi ja talletetaan muuttujaan
real x x = 1/2 ! x=?Kokonaislukujen jakolaskun tulos on kokonaisluku (osamäärän kokonaisosa)
x=1.0/2
Trigonometriset funktiot (kulmat aina radiaaneina!):
sin(x), cos(x), tan(x) asin(x), acos(x), atan(x), atan2(y,x)Hyperboliset funktiot:
sinh(x), cosh(x), tanh(x)Eksponentti, logaritmi ym.
exp(x), log(x), log10(x), sqrt(x)Minimi ja maksimi; argumenttien määrä mielivaltainen:
min(x, y, ...), max(x, y, ...)Itseisarvo
abs(x)Esim. muunnos pallokoordinaatistoon
real x,y,z,r,phi,theta real, parameter :: pi=3.141592654 x=-1.0 ; y=3.0; z=2.0 r=sqrt(x**2+y**2+z**2) phi=atan2(y,x)*180.0/pi theta=asin(z/r)*180.0/pi
== .eq. /= .ne. < .lt. <= .le. > .gt. >= .ge.Huom: = on sijoitusoperaattori; vertailu on ==.
integer n logical d d = n == 100*(n/100) ! tosi, jos n jaollinen 100:lla d = n .eq. 100*(n/100)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 {\tt X==.false.}.
logical leap, d4, d100, d400 integer y ... d4 = y==4*(y/4) d100 = y==100*(y/100) d400 = y==400*(y/400) leap = d4.and.(.not.d100 .or. d400)
x=1.0 y=exp(-x**2/2) z=1-ySamalla rivillä voi olla useita lauseita, jotka erotetaan puolipisteellä:
x = 1.0 ; y = 2.0 ; z = 0.1
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 ifLause(et) suoritetaan vain, jos ehto on voimassa, muulloin ei tehdä mitään
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
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
"Kone-epsilon" on pienin luku, joka ykköseen lisättynä antaa ykköstä suuremman tuloksen:
epsilon= min { x | 1+x > 1 }.
PC:n kaksoistarkkuuden lukuja vastaava konevakio on epsilon=2.2 x 10-16. Huom! tämä on hyvin paljon suurempi kuin pienin esitettävissä oleva positiivinen luku.
Delta a = ã - a.
Suhteellinen virhe on
e= (Delta a / a) = (ã - a) / a.
Usein a ei ole tiedossa, mutta Delta a tunnetaan esimerkiksi tilastollisten ominaisuuksien avulla. Arvio suhteelliselle virheelle on silloin
e ~ (Delta a / ã).
Pyöristys:
1.490 1, 1.5 1.551 2, 1.6 1.500 2 2.500 2Katkaisussa luvun loppuosa heitetään menemään.
Fortranissa muunnos reaaliluvusta kokonaisluvuksi tehdään katkaisemalla.
1.57 + 0.76 = 2.33.
Lasketaan summa pyöristämällä luvut yhteen desimaaliin:
1.6+0.8=2.4
Termien suhteelliset virheet ovat
(1.6-1.57)/1.57 = 0.019, (0.8-0.76)/0.76 = 0.053.
Summan suhteellinen virhe on
(2.4-2.33)/2.33 = 0.030.
Summan suhteellinen virhe ei koskaan voi olla suurempi kuin suurin yksittäisten positiivisten termien suhteellisista virheistä.
Muutetaan esimerkkiä hieman:
1.57 + 0.74 = 2.31.
1.6+0.7=2.3
Termien suhteelliset virheet ovat
(1.6-1.57)/1.57 = 0.019, (0.7-0.74)/0.74 = -0.054.
Summan suhteellinen virhe on
(2.3-2.31)/2.31 = -0.004.
Yhteenlasku on virheitä tasoittava operaatio, mikäli yksittäisten termien virheiden merkit ovat satunnaisia.
Ongelmia samanmerkkisten lukujen yhteenlasku voi aiheuttaa, kun lasketaan yhteen hyvin eri suuruisia lukuja. Jos esitystarkkuus on 7 desimaalia, on 1.0+3x10-8=1.0.
tarkka arvo likiarvo abs. virhe suht. virhe pi_1 3.160494 3.160 -0.00049 -0.00016 pi_2 3.142857 3.143 0.00014 0.00005 pi_1-pi_2 0.017637 0.017 - 0.00064 -0.03612Erotuksen suhteellinen virhe on paljon suurempi kuin alkuperäiset virheet, sillä mantissojen merkitsevimmät numerot kumoavat toisensa ja jäljelle jää alkuperäistä vähemmän merkitseviä numeroita (catastrophic cancellation).
Varo lähes yhtäsuurten lukujen vähennyslaskua!
Ongelmia aiheuttaa esimerkiksi
sqrt(1+x)-1,
kun x on pieni. Mikäli x<<1, voidaan neliöjuuri korvata Taylor-sarjan alkupäällä
sqrt(1+x)-1 ~ 1+(1/2)x-1 = (1/2)x.
Lauseke voidaan myös muuntaa toiseen muotoon
sqrt(1+x)-1 = x/(1+sqrt(1+x)).
Esimerkki: lasketaan integraali
In=\int01 xn/(x+10) dx
In+1+10In
= \int01 (xn+1/(x+10)+10xn/(x+10)) dx
= \int01 (xn(x+10)/(x+10) dx
= \int01 xn dx = 1/(n+1),
josta saadaan palautuskaava
In+1 = 1/(n+1) - 10In.
I_0=\int01 dx/(x+10) = ln 11 - ln 10 ~ 0.0953.
I_1 = (1/1) - 10 x 0.0953 = 0.0470, I_2 = (1/2) - 10 x 0.0470 = 0.0300, I_3 = (1/3) - 10 x 0.0300 = 0.0333, I_4 = (1/4) - 10 x 0.0333 = -0.0833. ????Nimittäjä on likimain vakio 10, joten
In ~ (1/10) \int01 xn dx = (1/10)(1/(n+1)).