Løkker#

Læringsutbytte

Etter å ha arbeidet med dette temaet, skal du kunne:

  1. bruke while- og for-løkker til å gjenta kode

  2. forklare når det passer å bruke en telleløkke, og når det passer å bruke en tilstandsløkke

  3. bruke range og lister i for-løkker

  4. bruke løkker til å behandle kjemiske data og utforske enkle kjemiske modeller

  5. lage og vurdere en enkel modell for tilfeldig partikkelbevegelse

Definisjon#

Den kanskje viktigste strukturen i programmering er løkker. De lar datamaskinen gjenta en operasjon så mange ganger vi vil. Det er dette som er en av datamaskinens store styrker.

I kjemi møter vi gjentakelser overalt. Vi kan utføre den samme beregningen for hver bølgelengde i et spektrum, undersøke hver måling i et datasett, oppdatere konsentrasjonene i en reaksjon for mange små tidssteg eller simulere bevegelsen til mange partikler. Uten løkker måtte vi ha skrevet den samme koden om igjen for hver måling, hvert tidssteg eller hver partikkel.

Løkker

En løkke er en struktur som gjør at vi kan gjenta kode. Ofte skiller vi mellom en telleløkke, som gjentar noe et bestemt antall ganger, og en tilstandsløkke, som gjentar noe så lenge et vilkår er sant. I Python heter disse henholdsvis for-løkke og while-løkke.

Vi begynner med en visuell framstilling av gjentakelser. Deretter skal vi bruke de samme prinsippene til å arbeide med kjemiske data og modeller.

Skilpaddegrafikk#

Vi skal først se hvordan løkker fungerer ved å introdusere deg for en skilpadde. Han heter Gunnar. Gunnar følger enkle kommandoer som forward, backward, right og left.

from turtle import *

shape("turtle")     # gir pekeren skilpaddeform
color("limegreen")  # gjør skilpadden limegrønn
forward(80)         # går framover 80 piksler
left(60)            # snur 60 grader mot venstre

Den første linja henter inn kommandoene fra biblioteket turtle. Et bibliotek er en samling ferdiglagde funksjoner som vi kan bruke i programmene våre. Vi har ikke laget funksjonene forward og left selv; de er definert i turtle-biblioteket.

En forenklet representasjon av en benzenring#

Et mulig kjemisk utgangspunkt er den sekskantede geometrien vi forbinder med benzen. Dersom vi skulle ha skrevet kommandoene én gang for hver side, måtte vi ha gjentatt forward(80) og left(60) seks ganger. Det er både tungvint og vanskelig å endre. Med en løkke kan vi skrive det slik:

from turtle import *

shape("turtle")
color("limegreen")
speed(3)

antall_sider = 6
sidelengde = 80
dreievinkel = 360 / antall_sider

for side in range(antall_sider):
    forward(sidelengde)
    left(dreievinkel)

done()

Løkka gjentar alt som er rykket inn seks ganger. Første gang løkka kjører, er side = 0. Deretter får side verdiene 1, 2, 3, 4 og 5. Funksjonen range(6) gir altså seks heltall fra og med 0 til, men ikke med, 6.

Underveisoppgave

  1. Hvorfor snur skilpadden 60° når vinklene mellom bindingene i den plane benzenringen er omtrent 120°?

  2. Hvilken funksjon har variabelen side i programmet?

  3. Hva må endres dersom du vil tegne ringen med kortere sider?

Tilfeldighet og random-biblioteket#

Bevegelsen til partikler i en væske eller gass påvirkes av et enormt antall kollisjoner. Vi kan ikke følge alle disse kollisjonene direkte i en enkel modell. I stedet kan vi la en partikkel velge en tilfeldig retning for hvert steg. Da trenger vi funksjonalitet fra random-biblioteket, som følger med Python.

Vi begynner med å importere funksjonen choice:

from random import choice

mulige_retninger = [0, 90, 180, 270]
retning = choice(mulige_retninger)

print(retning)

Kommandoen from random import choice betyr at vi henter funksjonen choice fra biblioteket random. Funksjonen velger ett tilfeldig element fra ei liste. Dersom du kjører programmet flere ganger, kan du derfor få ulike retninger.

Tidligere skrev vi from turtle import *. Stjerna betyr at vi importerer alle navnene i biblioteket. Det er praktisk i små turtle-programmer. Fra random trenger vi derimot bare én funksjon, og derfor importerer vi bare choice.

Datamaskinen lager egentlig pseudotilfeldige tall: De blir generert av en algoritme, men oppfører seg tilfeldig nok for denne modellen. Senere kan det være nyttig å kontrollere den tilfeldige tallfølgen slik at en simulering kan gjentas nøyaktig, men det trenger vi ikke gjøre her.

Tilfeldig vandring som diffusjonsmodell#

Vi kan nå kombinere choice med turtle og en for-løkke:

from turtle import *
from random import choice

shape("turtle")
speed(0)
pensize(2)

mulige_retninger = [0, 90, 180, 270]
antall_steg = 200
steglengde = 10

dot(10, "red")            # startpunkt

for steg in range(antall_steg):
    retning = choice(mulige_retninger)
    setheading(retning)
    forward(steglengde)

dot(10, "blue")           # sluttpunkt
done()

For hvert steg velger programmet én av fire retninger med lik sannsynlighet. Kommandoen setheading peker Gunnar i den valgte retningen, og forward flytter ham ett steg. Den røde prikken viser startpunktet, mens den blå viser sluttpunktet.

Dette er en tilfeldig vandring. Modellen kan illustrere hvordan mange tilfeldige bevegelser kan gi en netto forflytning over tid. Samtidig er den svært forenklet:

  • Et molekyl beveger seg i tre dimensjoner, mens Gunnar beveger seg i to.

  • Et molekyl kan bevege seg i langt flere enn fire retninger.

  • Bevegelsen skjer ikke i like lange steg på et rutenett.

  • Én bane viser bevegelsen til én modellpartikkel, ikke hvordan en hel samling partikler sprer seg.

Modellen er altså ikke en bokstavelig framstilling av molekylbevegelse. Den kan likevel hjelpe oss med å utforske noen grunnleggende trekk ved diffusjon.

Underveisoppgave

Kjør programmet flere ganger dersom du har en editor som støtter turtle-grafikk.

  1. Får partikkelen samme sluttposisjon hver gang?

  2. Hva skjer dersom du øker antall_steg?

  3. Hva skjer dersom du endrer steglengde?

  4. Hvorfor kan vi ikke konkludere om diffusjon ut fra bare én tilfeldig bane?

While-løkker#

En while-løkke er en tilstandsløkke. Den gjentar kode så lenge et vilkår er sant. Vi bruker ofte en while-løkke når vi ikke vet på forhånd nøyaktig hvor mange gjentakelser som trengs.

Anta at vi gjennomfører en serie 1:2-fortynninger. Etter hver fortynning er konsentrasjonen halvparten av den forrige. Vi ønsker å finne hvor mange fortynninger som trengs før konsentrasjonen blir lavere enn en bestemt grense.

konsentrasjon = 0.80       # mol/L
grense = 0.05              # mol/L
antall_fortynninger = 0

while konsentrasjon >= grense:
    print(f"Etter {antall_fortynninger} fortynninger: {konsentrasjon:.3f} mol/L")
    konsentrasjon = konsentrasjon / 2
    antall_fortynninger = antall_fortynninger + 1

print(f"Konsentrasjonen er nå {konsentrasjon:.3f} mol/L.")

Før hver løkkerunde undersøker Python om konsentrasjon >= grense er sant. Dersom det er sant, utføres de tre linjene som er rykket inn. Deretter undersøkes vilkåret på nytt. Når konsentrasjonen har blitt lavere enn grensa, er vilkåret usant og løkka avsluttes.

Det er avgjørende at noe inni løkka kan gjøre vilkåret usant. Dersom vi glemmer å oppdatere konsentrasjon, vil vilkåret alltid være sant og programmet fortsetter i en uendelig løkke.

Underveisoppgave

Les programmet linje for linje og forutsi hvor mange fortynninger som trengs. Hva skjer dersom vilkåret endres fra >= til >? Lag gjerne en løkketabell med kolonnene løkkerunde, konsentrasjon og antall fortynninger.

Du kan kjøre og endre fortynningsprogrammet i editoren nedenfor.

For-løkker#

En for-løkke er en telleløkke. Den passer godt når vi vet hvor mange ganger noe skal gjentas, eller når vi vil gjøre den samme operasjonen for hvert element i ei liste.

range-funksjonen#

Funksjonen range lager en sekvens av heltall som vi kan gå gjennom med en løkke:

Kommando

Verdier

range(3)

0, 1, 2

range(2, 4)

2, 3

range(1, 8, 2)

1, 3, 5, 7

Vi kan skrive en generell range-kommando som range(fra og med, til, steglengde). Det siste tallet er ikke med. Dersom vi bare bruker ett argument, starter sekvensen på 0. Dersom vi ikke oppgir steglengde, brukes steglengde 1.

for måling in range(5):
    print(f"Gjennomfører måling nummer {måling + 1}")

Variabelen måling får verdiene 0, 1, 2, 3 og 4. Vi legger til 1 i utskriften fordi mennesker vanligvis nummererer den første målingen som måling 1, ikke måling 0.

Løkker gjennom lister#

Vi trenger ikke alltid range. Dersom vi vil behandle alle verdiene i ei liste, kan løkkevariabelen få selve verdiene direkte:

absorbansverdier = [0.42, 0.39, 0.44, 0.41]
total_absorbans = 0

for absorbans in absorbansverdier:
    total_absorbans = total_absorbans + absorbans

gjennomsnitt = total_absorbans / len(absorbansverdier)
print(f"Gjennomsnittlig absorbans: {gjennomsnitt:.3f}")

Første gang løkka kjører, er absorbans = 0.42. Neste gang er absorbans = 0.39, og slik fortsetter det til alle elementene er brukt. Variabelen total_absorbans oppdateres for hver måling. Etter løkka deler vi totalen på antall målinger.

Å følge variablene gjennom ei løkke#

Vi kan systematisere løkkene med en løkketabell. Den holder styr på verdiene til variablene underveis:

konsentrasjon = 0.80

for trinn in range(4):
    konsentrasjon = konsentrasjon / 2

Underveisoppgave

Fyll inn resten av løkketabellen. Tabellen skal vise verdien til variablene etter at den innrykkede kodelinja er utført i hver løkkerunde.

Løkkerunde

trinn

konsentrasjon etter fortynning (mol/L)

Startverdi

0,80

1

0

0,40

2

1

3

4

Løkka går fire ganger selv om den siste verdien til trinn er 3. Dette er en vanlig kilde til misforståelser: Vi teller fire verdier, men starter på 0.

I noen løkker trenger vi ikke å bruke tellevariabelen. Da er det vanlig å kalle den _ for å vise at verdien ikke er viktig:

mengde = 10.0  # mg

for _ in range(5):
    mengde = mengde / 2

print(f"Etter fem halveringstider gjenstår {mengde:.3f} mg.")

Underveisoppgave

Skriv om programmet ovenfor slik at det skriver ut mengden etter hver halveringstid. Dersom du vil ha med nummeret på halveringstida i utskriften, bør du da fortsatt bruke _ som løkkevariabel?

Å tenke i løkker#

Løkker kan brukes til alt fra å summere tallrekker til å behandle måledata og utforske hvordan kjemiske systemer utvikler seg over tid. Når vi bruker løkker, må vi dele problemet opp i trinn som kan gjentas.

I matematikk og naturvitenskap representerer vi ofte sammenhenger med kontinuerlige funksjoner og formler. I et program kan vi i stedet utføre en liten operasjon om gangen. Dette kalles å løse problemet iterativt, fordi iterasjon betyr gjentakelse. Litt mer uformelt kan vi kalle det å løse et problem trinnvis med små, repeterende operasjoner for «å tenke i løkker».

Behandling av kjemiske data#

Løkker er nyttige når det samme kriteriet skal brukes på mange målinger. Anta at absorbansverdier mellom 0,10 og 1,00 ligger i det anbefalte arbeidsområdet for en bestemt analysemetode. Vi kan hente ut de aktuelle målingene slik:

absorbansverdier = [0.08, 0.42, 0.39, 1.18, 0.44]
gyldige_målinger = []

for absorbans in absorbansverdier:
    if 0.10 <= absorbans <= 1.00:
        gyldige_målinger.append(absorbans)

print(gyldige_målinger)

Her kombinerer vi ei liste, ei for-løkke og et vilkår. Hver absorbansverdi vurderes etter tur. Bare verdiene som oppfyller kriteriet, legges til i den nye lista.

Det anbefalte absorbansområdet er bare et eksempel. I en virkelig analyse må grensene bestemmes ut fra instrumentet, kalibreringen og metoden som brukes. Et program kan anvende kriteriene konsekvent, men det kan ikke avgjøre om kriteriene er faglig gode.

En enkel kinetisk modell#

Vi kan også bruke ei løkke til å undersøke hvordan en reaksjon utvikler seg over tid. Vi ser på den irreversible reaksjonen

\[A \rightarrow B\]

og antar at reaksjonsfarten er proporsjonal med konsentrasjonen av A:

\[v = k[A]\]

I løpet av et lite tidssteg \(\Delta t\) kan vi tilnærme konsentrasjonsendringen som

\[\Delta[A] \approx -k[A]\Delta t\]

Da kan vi oppdatere konsentrasjonene litt etter litt:

k = 0.15             # ratekonstant i s^-1
A = 1.00             # startkonsentrasjon av A i mol/L
B = 0.00             # startkonsentrasjon av B i mol/L
dt = 0.10            # tidssteg i s
tid_slutt = 10       # sluttid i s

antall_steg = int(tid_slutt / dt)

for steg in range(antall_steg):
    endring = k * A * dt
    A = A - endring
    B = B + endring

print(f"Etter {tid_slutt} s er [A] = {A:.3f} mol/L.")
print(f"Etter {tid_slutt} s er [B] = {B:.3f} mol/L.")
print(f"Total konsentrasjon: {A + B:.3f} mol/L.")

For hvert tidssteg beregner vi først hvor mye A som omdannes. Den samme endringen trekkes fra A og legges til B. Dermed bevares den totale konsentrasjonen i denne forenklede modellen.

Dette er en numerisk tilnærming. Vi antar blant annet at reaksjonsfarten er omtrent konstant innenfor hvert lite tidssteg. Dersom dt er for stor, blir tilnærmingen dårligere. Senere skal vi se nærmere på slike simuleringer og hvordan vi kan teste om resultatene er pålitelige.

Underveisoppgave

Kjør programmet med dt = 1, dt = 0.1 og dt = 0.01. Hvordan påvirkes sluttverdien til A? Hvorfor må antall_steg endres når tidssteget endres?

Tallfølger og rekkesummer#

Løkker brukes ofte til å generere tallfølger. En tallfølge er en oppramsing av tall som kan være endelig eller uendelig. Etter hver halveringstid er for eksempel andelen av et radioaktivt stoff som gjenstår

\[1,\ \frac{1}{2},\ \frac{1}{4},\ \frac{1}{8},\ \frac{1}{16},\ldots\]

Hvert tall i en tallfølge kalles et ledd. Dersom \(N_n\) er mengden etter \(n\) halveringstider, kan vi beskrive følgen rekursivt:

\[N_{n+1}=\frac{1}{2}N_n\]

En rekursiv formel bruker altså en tidligere verdi til å beregne den neste. Det passer svært godt med ei løkke:

mengde = 4.0  # kg

for antall_halveringstider in range(11):
    print(f"n = {antall_halveringstider}: {mengde:.6f} kg")
    mengde = mengde / 2

Programmet skriver først ut startmengden ved \(n=0\). Deretter oppdateres mengden før neste løkkerunde.

Når vi beskriver en tallfølge som en serie av tall som adderes, kaller vi det ei rekke. Et matematisk eksempel er den uendelige geometriske rekka

\[1 + \frac{2}{3} + \frac{4}{9} + \frac{8}{27} + \ldots\]

Det \(n\)-te leddet kan skrives som \((2/3)^n\). En datamaskin kan ikke summere uendelig mange ledd, men vi kan tilnærme summen med et stort, endelig antall:

antall_ledd = 100
summen = 0

for n in range(antall_ledd):
    ledd = (2 / 3)**n
    summen = summen + ledd

print(summen)

Den analytiske summen er 3. Programmet gir en verdi som er svært nær 3, men dette er fremdeles en numerisk tilnærming. Eksemplet viser også et generelt mønster som vi ofte bruker i kjemiske beregninger: Vi begynner med en startverdi, beregner et nytt bidrag og oppdaterer en akkumulert verdi for hver løkkerunde.

Underveisoppgave

Modifiser programmet slik at det bruker en while-løkke og fortsetter å summere helt til det neste leddet er mindre enn \(10^{-8}\). Hvorfor passer en while-løkke godt når stoppkriteriet formuleres på denne måten?

Nøstede løkker#

Nøstede løkker er løkker inni løkker. Da gjentas den innerste løkka for hver runde i den ytterste løkka.

Et kjemisk eksempel er elektronoverganger i hydrogenatomet. Dersom elektronet starter i nivå \(n\), kan det deeksitere til alle nivåer \(m<n\). Vi kan skrive ut overgangene fra nivåene 2 til og med 5 slik:

for n in range(2, 6):
    for m in range(1, n):
        print(f"Mulig overgang: n = {n} til m = {m}")

Når n = 2, får den indre løkka bare verdien m = 1. Når n = 3, får m verdiene 1 og 2. Den indre løkka blir altså lengre for hvert nye energinivå. Totalt skriver programmet ut \(1+2+3+4=10\) mulige overganger.

Underveisoppgave

Utvid programmet til startnivåene 2–7. Hvor mange overganger blir skrevet ut? Modifiser deretter programmet slik at det bare skriver ut overganger som ender i nivået m = 2.

Oppgaver#

Oppgave 4.1

Sammenlikn programmene nedenfor. Beskriv forskjeller og likheter. Hva blir skrevet ut?

konsentrasjon = 0.80

for trinn in range(4):
    konsentrasjon = konsentrasjon / 2
    print(konsentrasjon)
konsentrasjon = 0.80
trinn = 0

while trinn < 4:
    konsentrasjon = konsentrasjon / 2
    print(konsentrasjon)
    trinn = trinn + 1

Oppgave 4.2

Lag en løkketabell med løkkerunde, i, mengde og målt_mengde for følgende program:

mengde = 8.0

for i in range(4):
    mengde = mengde / 2
    målt_mengde = mengde * 0.95

Oppgave 4.3

Lag et program som skriver ut «Måling registrert» fem ganger. Hvilken funksjon har løkkevariabelen? Velg et variabelnavn som viser om verdien brukes eller ikke.

Oppgave 4.4

Programmet nedenfor skal finne summen av de åtte første tallene i en tallfølge der hvert ledd er det dobbelte av det forrige. Forklar hvordan programmet fungerer, og finn ut hvilke åtte tall som summeres.

tall = 1
summen = 0

for _ in range(8):
    summen = summen + tall
    tall = tall * 2

print(summen)

Oppgave 4.5

Skriv om programmet i oppgave 4.4 slik at det bruker en while-løkke i stedet for en for-løkke.

Oppgave 4.6

Hva skrives ut i følgende program? Undersøk først programmet for hånd, og kontroller deretter svaret i en editor.

konsentrasjon = 1.0

for i in range(4):
    print(i, konsentrasjon)
    konsentrasjon = konsentrasjon / 2

print("Slutt:", konsentrasjon)

Oppgave 4.7

Bruk turtle-grafikk til å tegne en enkel sikksakk-kjede med ti bindinger. La Gunnar skifte mellom å svinge 60° mot venstre og 60° mot høyre. Du kan bruke modulusoperatoren (%) og et vilkår til å skille mellom partall og oddetall.

Hvordan skiller denne todimensjonale strektegningen seg fra en molekylmodell?

Oppgave 4.8

Modifiser programmet for tilfeldig vandring slik at partikkelen kan bevege seg i åtte retninger: 0°, 45°, 90°, 135°, 180°, 225°, 270° og 315°. Sammenlikn banene med modellen som bare bruker fire retninger. Hvilken modell ser mest kontinuerlig ut? Hvilke viktige forenklinger gjenstår?

Oppgave 4.9

En analyse gir absorbansverdiene [0.08, 0.42, 0.39, 1.18, 0.44, 0.41]. I denne oppgaven regner vi verdier fra og med 0,10 til og med 1,00 som gyldige.

Lag et program som

  1. teller antall gyldige og ugyldige målinger

  2. beregner gjennomsnittet av de gyldige målingene

  3. gir en egen beskjed dersom ingen målinger er gyldige.

Oppgave 4.10

En løsning har startkonsentrasjon 1,00 mol/L. Den fortynnes gjentatte ganger 1:2. Lag et program som fortsetter til konsentrasjonen er lavere enn 0,010 mol/L. Programmet skal skrive ut antall fortynninger og sluttkonsentrasjonen.

Oppgave 4.11

Utvid den kinetiske modellen for \(A \rightarrow B\) slik at programmet lagrer tid og konsentrasjonen av A i hver sine lister. Plott deretter \([A]\) som funksjon av tid. Kjør modellen med minst to ulike tidssteg og sammenlikn kurvene.

Oppgave 4.12

Når et elektron i et hydrogenatom deeksiterer fra energinivå \(n\) til et lavere nivå \(m\), er energien til det emitterte fotonet

\[\Delta E = B\left(\frac{1}{m^2}-\frac{1}{n^2}\right),\]

der \(B=2{,}18\cdot10^{-18}\) J. Vi bruker også sammenhengene \(\Delta E=hf\) og \(\lambda=c/f\).

a) Beregn bølgelengden ved overgangen fra \(n=5\) til \(m=2\). Dette skal gi omtrent 434 nm.

b) Bruk ei løkke til å beregne alle mulige bølgelengder fra ett valgt startnivå n.

c) Bruk nøstede løkker til å beregne alle mulige overganger fra startnivåene 2–6.

Oppgave 4.13

Mengden av en radioaktiv isotop etter tida \(t\) kan modelleres som

\[N(t)=N_0e^{-at},\]

der \(a=\ln(2)/T\) og \(T\) er halveringstida. Plutonium-239 har en halveringstid på omtrent 24 000 år.

Skriv et program som skriver ut hvor mye som gjenstår for hvert 5000. år over en periode på 50 000 år dersom startmengden er 4,0 kg.

Oppgave 4.14

Ideelle gasser kan beskrives med likningen

\[PV=nRT.\]

Lag ei liste med trykk fra 100 til og med 400 kPa med steg på 25 kPa. Bruk ei løkke til å beregne volumet i liter for 1,00 mol ideell gass ved 298 K. Lagre volumene i ei liste og plott volum som funksjon av trykk.

Pass på enhetene: Gasskonstanten \(R=8{,}314\) Pa m\(^3\) K\(^{-1}\) mol\(^{-1}\) krever trykk i pascal og gir volum i m\(^3\).

Oppgave 4.15

Vi vil undersøke hvordan startkonsentrasjonen og ratekonstanten påvirker den kinetiske modellen for \(A \rightarrow B\). Bruk nøstede løkker til å simulere alle kombinasjonene av

  • startkonsentrasjoner = [0.50, 1.00] mol/L

  • ratekonstanter = [0.05, 0.10, 0.20] s\(^{-1}\).

Bruk dt = 0.01 s og tid_slutt = 10 s. Skriv ut sluttkonsentrasjonen av A for hver kombinasjon.

Oppgave 4.16

Lag et program som regner ut summen

\[\sum_{n=0}^{50}\frac{1}{2^n}.\]

Løs oppgaven både med en for-løkke og en while-løkke.

Oppgave 4.17

Fibonaccifølgen er en kjent tallfølge der hvert tall etter de to første er summen av de to foregående:

\[1,1,2,3,5,8,13,21,\ldots\]

Lag et program som skriver ut de første n tallene i følgen.

Oppgave 4.18

I kombinatorikk er \(n\)-fakultet definert som produktet av alle heltall fra og med 1 til og med \(n\):

\[n!=\prod_{k=1}^{n}k.\]

Lag et program som regner ut fakultetet til et positivt heltall.

Oppgave 4.19

Eksponentialfunksjonen kan tilnærmes med et Taylorpolynom:

\[e^x\approx\sum_{i=0}^{n-1}\frac{x^i}{i!}.\]

Lag en funksjon exp_taylor(x, n) som beregner tilnærmingen med n ledd. Bruk deretter ei løkke til å sammenlikne tilnærmingen med math.exp(x) for heltallene 1–10.

Videoer#

I videoene nedenfor kan du få en innføring eller repetisjon i den grunnleggende teorien bak løkker:

Når du har sett videoen, kan du gjøre følgende oppgave for å sjekke om du forstår innholdet:

Underveisoppgave

Skriv et program som regner ut summen av alle heltallene fra og med 1 til og med 449 ved hjelp av en for-løkke.

Når du har sett videoen, kan du gjøre følgende oppgave for å sjekke om du forstår innholdet:

Underveisoppgave

Skriv et program som regner ut summen av tallene fra og med 1 til og med 449 ved hjelp av en while-løkke.