9.3 Programmering med følger og rekker
Python-implementasjon av følger og rekker, iterasjon og visualisering.
Programmering er et kraftig supplement til analytisk matematikk. Når vi studerer følger og rekker, gir Python oss muligheten til å:
- Generere hundrevis av ledd umiddelbart, selv for kompliserte rekursive formler
- Visualisere konvergens og divergens grafisk
- Eksperimentere med parametre og se effekten umiddelbart
- Modellere praktiske situasjoner der analytiske formler er kompliserte
I dette kapitlet bruker vi to typer løkker:
- for-løkke: Når vi vet nøyaktig hvor mange iterasjoner vi trenger (f.eks. "beregn de første 50 leddene")
- while-løkke: Når vi itererer til en betingelse er oppfylt (f.eks. "kjør til feilen er under ")
Vi bruker matplotlib for plotting og math for matematiske funksjoner.
Lese et program
På eksamen skal du ofte forklare hva et program regner ut, eller finne hva det skriver ut. Da følger vi variablene gjennom løkka i en sporingstabell: én rad per runde, med verdiene etter at linjene i løkka er utført. Betingelsen i while sjekkes før hver runde.
a = 200
n = 0
while a > 100:
a = 0.8*a + 10
n = n + 1
print(n, round(a, 2))a) Hva skriver programmet ut?
b) Forklar hva programmet finner ut.
a)
| ? | ||
|---|---|---|
| 0 | ja | |
| 1 | ja | |
| 2 | ja | |
| 3 | ja | |
| 4 | ja | |
| 5 | nei |
Løkka stopper etter runde 5.
Svar: Programmet skriver ut
5 99.15.b)
Programmet regner ut leddene i følgen , til et ledd er 100 eller mindre.
Svar: Programmet finner at er det første leddet som ikke er større enn 100.
# Geometrisk følge: a_n = 100 *
# 0.85^(n-1)
a1 = 100
k = 0.85
for n in range(1, 21):
a_n = a1 * k ** (n - 1)
print(f"a_{n:>2} = {a_n:.4f}")Rekursive følger oppdaterer variabelen i hver iterasjon:
# Rekursiv: a_{n+1} = 0.7 * a_n +
# 15, a_1 = 200
a = 200
print(f"a_1 = {a:.4f}")
for n in range(2, 21):
a = 0.7 * a + 15
print(f"a_{n:>2} = {a:.4f}")
# Grenseverdi: L = 0.7L + 15 => L
# = 50Delsummer beregnes med en akkumulerende variabel:
import matplotlib.pyplot as plt
N = 100
S = 0
n_verdier = []
s_verdier = []
for n in range(1, N + 1):
# Legg til neste ledd
S += 1 / n**2
n_verdier.append(n)
s_verdier.append(S)
plt.plot(
n_verdier,
s_verdier,
"b-",
linewidth=1.5,
)
plt.axhline(
y=3.14159**2 / 6,
color="red",
linestyle="--",
label=(
r"$\pi^2/6 \approx"
r" 1.6449$"
),
)
plt.xlabel("n")
plt.ylabel("$S_n$")
plt.title(
"Delsummer av $\\sum 1/n^2$"
)
plt.legend()
plt.grid(True)
plt.show()En while-løkke er nyttig når vi ikke vet på forhånd hvor mange iterasjoner vi trenger. Et typisk brukstilfelle er å iterere til en følge har konvergert til ønsket presisjon.
Eksempel: Finne antall ledd til grenseverdien er nådd
# Geometrisk følge a_n = 500 *
# 0.9^(n-1)
# Finn første n slik at a_n < 1
a = 500
n = 1
while a >= 1:
a = a * 0.9
n += 1
print(
"Første n med a_n < 1: n ="
f" {n}, a_n = {a:.6f}"
)Eksempel: Iterasjon til konvergens
# Rekursiv: a_{n+1} = (a_n +
# 3/a_n) / 2 (kvadratrot av 3 med
# Newton-metoden)
import math
a = 2.0 # Startgjetning
toleranse = 1e-10
n = 0
while True:
a_ny = (a + 3 / a) / 2
n += 1
if abs(a_ny - a) < toleranse:
break
a = a_ny
print(
f"sqrt(3) = {a_ny:.12f} "
f" (etter {n} iterasjoner)"
)
print(
"math.sqrt(3) ="
f" {math.sqrt(3):.12f}"
)Newton-metoden konvergerer ekstremt raskt (kvadratisk konvergens): antall korrekte desimaler omtrent fordobles per iterasjon.
- plt.plot(x, y) - linjeplott (bra for delsummer og trender)
- plt.stem(x, y) - stemmeplott (bra for diskrete følger)
- plt.axhline(y=L) - horisontal linje (bra for grenseverdier)
- plt.yscale('log') - logaritmisk skala (bra for eksponentiell vekst)
GeoGebra er også et godt verktøy:
- Bruk Sekvens()-kommandoen for å generere følger
- Sekvens(k^2, k, 1, 10) gir
- Sum(Sekvens(1/k^2, k, 1, 100)) beregner delsummen
Begge verktøyene lar deg raskt eksperimentere med parametre og visuelt oppdage mønstre før du beviser dem analytisk.
Du tar opp et lån på 500 000 kr med 5 % nominell årlig rente. Du betaler 35 000 kr per år. La være restgjelden etter år.
a) Sett opp en rekursiv formel for .
b) Skriv et Python-program som beregner restgjelden for hvert år og plotter utviklingen.
c) Finn det første året der restgjelden er nedbetalt (under 0 kr).
Restgjelden vokser med 5 % rente, men reduseres med årsbetalingen.
b) Python-program:
import matplotlib.pyplot as plt
a = 500_000 # Startlån
rente = 1.05
betaling = 35_000
år = [0]
gjeld = [a]
n = 0
while a > 0:
a = a * rente - betaling
n += 1
år.append(n)
# Ikke vis negativ gjeld
gjeld.append(max(a, 0))
plt.figure(figsize=(10, 5))
plt.plot(
år, gjeld, "b-o", markersize=4
)
plt.axhline(
y=0,
color="red",
linestyle="--",
)
plt.xlabel("År")
plt.ylabel("Restgjeld (kr)")
plt.title(
"Lånamortisering: 500 000 kr"
" til 5 % rente"
)
plt.grid(True)
plt.show()
print(
"Lånet er nedbetalt etter"
f" {n} år."
)c) Resultat:
Programmet skriver ut «Lånet er nedbetalt etter 26 år.» Etter 25 år er restgjelden ca. 22 729 kr, og i år 26 blir den negativ.
Kontroll: Gjelden vokser bare dersom rentene er større enn betalingen på 35 000 kr, altså dersom kr. Siden , synker gjelden hvert år.
Eksplisitt formel: . Da gir at , altså .
Svar: a) med . c) Lånet er nedbetalt i løpet av år 26.
Bruk Python til å undersøke konvergensen av rekken for ulike verdier av .
a) Beregn delsummen for , , og .
b) Plott delsummene som funksjon av for disse fire verdiene av .
c) Kommenter hvilke verdier av som gir konvergens.
import matplotlib.pyplot as plt
N_max = 10000
p_verdier = [0.5, 1.0, 1.5, 2.0]
plt.figure(figsize=(10, 6))
for p in p_verdier:
S = 0
n_list = []
s_list = []
for n in range(1, N_max + 1):
S += 1 / n**p
if (
n % 100 == 0
or n <= 50
):
n_list.append(n)
s_list.append(S)
print(
f"p = {p}: S_10000 ="
f" {S:.6f}"
)
plt.plot(
n_list,
s_list,
label=f"p = {p}",
)
plt.xlabel("N")
plt.ylabel("$S_N$")
plt.title(
"Delsummer av $\\sum 1/n^p$"
)
plt.legend()
plt.grid(True)
plt.show()Resultater:
- : (divergerer)
- : (divergerer, men sakte)
- : (konvergerer langsomt mot )
- : (konvergerer mot )
Svar: c) Rekken konvergerer når og divergerer når .
der er vekstraten og er bæreevnen. Startpopulasjonen er .
a) Skriv et Python-program som beregner de 30 første leddene og plotter dem.
b) Hva skjer med populasjonen på lang sikt?
c) Kjør programmet med . Hvordan endrer forløpet seg?
import matplotlib.pyplot as plt
r = 0.8
K = 1000
# Startpopulasjon P_0
P = 100
N = 30
n_verdier = [0]
p_verdier = [P]
for n in range(1, N + 1):
P = P + r * P * (1 - P / K)
n_verdier.append(n)
p_verdier.append(P)
for n in range(11):
print(
f"P_{n:>2} ="
f" {p_verdier[n]:.1f}"
)
plt.figure(figsize=(10, 5))
plt.plot(
n_verdier,
p_verdier,
"b-o",
markersize=3,
)
plt.axhline(
y=K,
color="red",
linestyle="--",
label="Bæreevne K = 1000",
)
plt.xlabel("Generasjon n")
plt.ylabel("Populasjon P_n")
plt.title(
"Logistisk populasjonsmodell"
" (r = 0,8, K = 1000)"
)
plt.legend()
plt.grid(True)
plt.show()b) Analyse:
Programmet skriver ut , , , , , , , , , og .
Likevekt: gir , altså eller .
Populasjonen vokser først nesten eksponentielt, så bremser veksten, og følgen nærmer seg bæreevnen uten å gå over.
c) :
Programmet gir , , , , og .
Populasjonen går over bæreevnen og svinger rundt 1000 med stadig mindre utslag. For nærmer følgen seg .
Svar: b) Populasjonen nærmer seg bæreevnen . c) Med svinger populasjonen rundt 1000 med avtagende utslag, men nærmer seg fortsatt 1000.
# a_n = n^2 + 3n for n = 1, ...,
# 20
a = [
n**2 + 3 * n
for n in range(1, 21)
]sum() med generatoruttrykk for raske summer uten å lagre alle ledd:
# Sum av 10 000 ledd
S = sum(
1 / n**2
for n in range(1, 10001)
)enumerate() gir både indeks og verdi:
for i, verdi in enumerate(a, 1):
print(f"a_{i} = {verdi}")Logaritmisk skala for følger som vokser raskt:
# Y-aksen i logaritmisk skala
plt.yscale('log')plt.stem() passer for diskrete følger (enkeltpunkter med loddrette linjer), plt.plot() for trender og delsummer.
- Indeksfeil: Python bruker 0-indeksering, men matematiske følger starter gjerne på . Pass på range(1, N+1) vs. range(N).
- Overskriving av variabel: I rekursive følger må du oppdatere variabelen etter at du har brukt den gamle verdien. Skriv a_ny = f(a) først, deretter a = a_ny.
- Flyttallsfeil: Python bruker flyttall med begrenset presisjon (~15 desimaler). For veldig mange iterasjoner kan avrundingsfeil hope seg opp.
- Uendelig løkke: En while-løkke uten korrekt stoppbetingelse kjører for alltid. Legg alltid inn en maksimumsgrense: while a >= 1 and n < 10000:.
Grunnleggende programmering av følger
Skriv et Python-program som bruker en for-løkke til å skrive ut de 15 første leddene i den aritmetiske følgen og beregner summen . Verifiser summen analytisk med formelen .
Skriv et Python-program som genererer de 20 første leddene i den rekursive følgen , og plotter dem med matplotlib. Legg inn en stiplet linje for grenseverdien.
Bruk en while-løkke til å finne det første leddet i følgen som er mindre enn .
Delsummer og konvergens
Skriv et Python-program som beregner delsummene for . Sammenlign med Aperys konstant .
Plott delsummene for (den alternerende harmoniske rekken). Hva er grenseverdien?
Figurtall med programmering
Skriv et Python-program som beregner og plotter de 20 første trekantallene og de 20 første kvadrattallene i samme figur.
Verifiser med Python at for ved å sjekke at differansen er null for alle .
Praktisk modellering og tilnærminger
Du investerer 5 000 kr ved starten av hvert år i et fond med fast årlig avkastning. Skriv et Python-program som beregner og plotter formuen for tre ulike avkastninger: 3 %, 7 % og 10 % over 30 år. Kommenter effekten av renteforskjellen.
Skriv et Python-program som bruker Newtons metode () til å beregne for . Start med og kjør til . Skriv ut hvert ledd og antall korrekte desimaler.
Bruk Python til å estimere ved hjelp av Leibniz-formelen: . Plott feilen som funksjon av i logaritmisk skala. Hvor mange ledd trenger du for 6 korrekte desimaler?
Se på programmet.
S = 0
for n in range(1, 6):
S = S + 3*n + 1
print(S)Lag en sporingstabell og finn hva programmet skriver ut.
Forklar hva programmet regner ut.
Se på programmet.
S = 0
n = 0
while S < 1000:
n = n + 1
S = S + 3*n + 1
print(n, S)Forklar hva programmet finner ut.
Summen av de første leddene er . Bruk dette til å finne hva programmet skriver ut.
Se på programmet.
saldo = 10000
ar = 0
while saldo < 20000:
saldo = saldo * 1.05 + 1000
ar = ar + 1
print(ar, round(saldo))Forklar hva programmet regner ut.
Lag en sporingstabell og finn hva programmet skriver ut.
Oppsummering
Læringspunkter:
- For-løkker passer når antall iterasjoner er kjent; while-løkker når man itererer til en betingelse er oppfylt (f.eks. «første ledd under 200»).
- Rekursive følger programmeres ved å oppdatere en variabel: a = p*a + q inne i løkka.
- Delsummer beregnes ved å akkumulere ledd i en sumvariabel — og kan brukes til å utforske konvergens numerisk.
- Numeriske metoder som Newtons metode ( for ) er rekursive følger som konvergerer raskt.
- Leibniz-rekken konvergerer svært langsomt — valg av algoritme betyr mye.
| Nøkkelbegrep | Forklaring |
|---|---|
| For-løkke | Gjentar et kjent antall ganger |
| While-løkke | Gjentar til en betingelse brytes |
| Akkumulator | Variabel som samler opp en sum |
| Newtons metode | Rekursiv tilnærming til røtter/nullpunkter |
| Konvergenshastighet | Hvor raskt en metode nærmer seg svaret |
Viktige formler:
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.