9.3 Programmering med følgjer og rekkjer
Python-implementasjon av følgjer og rekkjer, iterasjon og visualisering.
Programmering er eit kraftig supplement til analytisk matematikk. Når vi studerer følgjer og rekkjer, gir Python oss høve til å:
- Generere hundrevis av ledd med ein gong, sjølv for kompliserte rekursive formlar
- Visualisere konvergens og divergens grafisk
- Eksperimentere med parametrar og sjå effekten med ein gong
- Modellere praktiske situasjonar der analytiske formlar er kompliserte
I dette kapittelet bruker vi to typar løkker:
- for-løkke: Når vi veit nøyaktig kor mange iterasjonar vi treng (t.d. "rekn ut dei første 50 ledda")
- while-løkke: Når vi itererer til ein vilkår er oppfylt (t.d. "køyr til feilen er under ")
Vi bruker matplotlib for plotting og math for matematiske funksjonar.
Lese eit program
På eksamen skal du ofte forklare kva eit program reknar ut, eller finne kva det skriv ut. Då følgjer vi variablane gjennom løkka i ein sporingstabell: éi rad per runde, med verdiane etter at linjene i løkka er utførte. Vilkåret i while blir sjekka før kvar runde.
a = 200
n = 0
while a > 100:
a = 0.8*a + 10
n = n + 1
print(n, round(a, 2))a) Kva skriv programmet ut?
b) Forklar kva programmet finn ut.
a)
| ? | ||
|---|---|---|
| 0 | ja | |
| 1 | ja | |
| 2 | ja | |
| 3 | ja | |
| 4 | ja | |
| 5 | nei |
Løkka stoppar etter runde 5.
Svar: Programmet skriv ut
5 99.15.b)
Programmet reknar ut ledda i følgja , til eit ledd er 100 eller mindre.
Svar: Programmet finn at er det første leddet som ikkje 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ølgjer oppdaterer variabelen i kvar 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
# = 50Delsummar blir rekna ut med ein akkumulerande 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()Ei while-løkke er nyttig når vi ikkje veit på førehand kor mange iterasjonar vi treng. Eit typisk brukstilfelle er å iterere til ei følgje har konvergert til ønskt presisjon.
Eksempel: Finne talet på 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): talet på korrekte desimalar blir omtrent fordobla per iterasjon.
- plt.plot(x, y) - linjeplott (bra for delsummar og trendar)
- plt.stem(x, y) - stemmeplott (bra for diskrete følgjer)
- plt.axhline(y=L) - horisontal linje (bra for grenseverdiar)
- plt.yscale('log') - logaritmisk skala (bra for eksponentiell vekst)
GeoGebra er òg eit godt verktøy:
- Bruk Sekvens()-kommandoen for å generere følgjer
- Sekvens(k^2, k, 1, 10) gir
- Sum(Sekvens(1/k^2, k, 1, 100)) reknar ut delsummen
Begge verktøya lèt deg raskt eksperimentere med parametrar og visuelt oppdage mønster før du bevis dei analytisk.
Du tek opp eit lån på 500 000 kr med 5 % nominell årleg rente. Du betaler 35 000 kr per år. Lat vere restgjelda etter år.
a) Set opp ein rekursiv formel for .
b) Skriv eit Python-program som reknar ut restgjelda for kvart år og plottar utviklinga.
c) Finn det første året der restgjelda er nedbetalt (under 0 kr).
Restgjelda veks med 5 % rente, men blir redusert med årsbetalinga.
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 skriv ut «Lånet er nedbetalt etter 26 år.» Etter 25 år er restgjelda om lag 22 729 kr, og i år 26 blir ho negativ.
Kontroll: Gjelda veks berre dersom rentene er større enn betalinga på 35 000 kr, altså dersom kr. Sidan , minkar gjelda kvart år.
Eksplisitt formel: . Då gir at , altså .
Svar: a) med . c) Lånet er nedbetalt i løpet av år 26.
Bruk Python til å undersøkje konvergensen av rekkja for ulike verdiar av .
a) Rekn ut delsummen for , , og .
b) Plott delsummane som funksjon av for desse fire verdiane av .
c) Kommenter kva verdiar 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()Resultat:
- : (divergerer)
- : (divergerer, men sakte)
- : (konvergerer langsamt mot )
- : (konvergerer mot )
Svar: c) Rekkja konvergerer når og divergerer når .
der er vekstraten og er bereevna. Startpopulasjonen er .
a) Skriv eit Python-program som reknar ut dei 30 første ledda og plottar dei.
b) Kva skjer med populasjonen på lang sikt?
c) Køyr programmet med . Korleis endrar 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 skriv ut , , , , , , , , , og .
Likevekt: gir , altså eller .
Populasjonen veks først nesten eksponentielt, så bremsar veksten, og følgja nærmar seg bereevna utan å gå over.
c) :
Programmet gir , , , , og .
Populasjonen går over bereevna og svingar rundt 1000 med stadig mindre utslag. For nærmar følgja seg .
Svar: b) Populasjonen nærmar seg bereevna . c) Med svingar populasjonen rundt 1000 med minkande utslag, men nærmar seg framleis 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 summar utan å 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ølgjer som veks raskt:
# Y-aksen i logaritmisk skala
plt.yscale('log')plt.stem() passar for diskrete følgjer (enkeltpunkt med loddrette linjer), plt.plot() for trendar og delsummar.
- Indeksfeil: Python bruker 0-indeksering, men matematiske følgjer startar gjerne på . Pass på range(1, N+1) vs. range(N).
- Overskriving av variabel: I rekursive følgjer må du oppdatere variabelen etter at du har brukt den gamle verdien. Skriv a_ny = f(a) først, deretter a = a_ny.
- Flyttalsfeil: Python bruker flyttal med avgrensa presisjon (~15 desimalar). For veldig mange iterasjonar kan avrundingsfeil hope seg opp.
- Uendeleg løkke: Ei while-løkke utan korrekt stoppvilkår køyrer for alltid. Legg alltid inn ei maksimumsgrense: while a >= 1 and n < 10000:.
Grunnleggjande programmering av følgjer
Skriv eit Python-program som bruker ei for-løkke til å skrive ut dei 15 første ledda i den aritmetiske følgja og reknar ut summen . Verifiser summen analytisk med formelen .
Skriv eit Python-program som genererer dei 20 første ledda i den rekursive følgja , og plottar dei med matplotlib. Legg inn ei stipla linje for grenseverdien.
Bruk ei while-løkke til å finne det første leddet i følgja som er mindre enn .
Delsummar og konvergens
Skriv eit Python-program som reknar ut delsummane for . Samanlikn med Aperys konstant .
Plott delsummane for (den alternerande harmoniske rekkja). Kva er grenseverdien?
Figurtal med programmering
Skriv eit Python-program som reknar ut og plottar dei 20 første trekanttala og dei 20 første kvadrattala i same figur.
Verifiser med Python at for ved å sjekke at differansen er null for alle .
Praktisk modellering og tilnærmingar
Du investerer 5 000 kr ved starten av kvart år i eit fond med fast årleg avkastning. Skriv eit Python-program som reknar ut og plottar formuen for tre ulike avkastingar: 3 %, 7 % og 10 % over 30 år. Kommenter effekten av renteforskjellen.
Skriv eit Python-program som bruker Newtons metode () til å rekne ut for . Start med og køyr til . Skriv ut kvart ledd og talet på korrekte desimalar.
Bruk Python til å estimere ved hjelp av Leibniz-formelen: . Plott feilen som funksjon av i logaritmisk skala. Kor mange ledd treng du for 6 korrekte desimalar?
Sjå på programmet.
S = 0
for n in range(1, 6):
S = S + 3*n + 1
print(S)Lag ein sporingstabell og finn kva programmet skriv ut.
Forklar kva programmet reknar ut.
Sjå på programmet.
S = 0
n = 0
while S < 1000:
n = n + 1
S = S + 3*n + 1
print(n, S)Forklar kva programmet finn ut.
Summen av dei første ledda er . Bruk dette til å finne kva programmet skriv ut.
Sjå på programmet.
saldo = 10000
ar = 0
while saldo < 20000:
saldo = saldo * 1.05 + 1000
ar = ar + 1
print(ar, round(saldo))Forklar kva programmet reknar ut.
Lag ein sporingstabell og finn kva programmet skriv ut.
Oppsummering
Læringspunkt:
- For-løkker passar når talet på iterasjonar er kjent; while-løkker når ein itererer til ein vilkår er oppfylt (t.d. «første ledd under 200»).
- Rekursive følgjer blir programmerte ved å oppdatere ein variabel: a = p*a + q inne i løkka.
- Delsummar blir rekna ut ved å akkumulere ledd i ein sumvariabel — og kan brukast til å utforske konvergens numerisk.
- Numeriske metodar som Newtons metode ( for ) er rekursive følgjer som konvergerer raskt.
- Leibniz-rekkja konvergerer svært langsamt — val av algoritme tyder mykje.
| Nøkkelomgrep | Forklaring |
|---|---|
| For-løkke | Gjentek eit kjent tal gonger |
| While-løkke | Gjentek til ein vilkår blir broten |
| Akkumulator | Variabel som samlar opp ein sum |
| Newtons metode | Rekursiv tilnærming til røter/nullpunkt |
| Konvergenshastigheit | Kor raskt ein metode nærmar seg svaret |
Viktige formlar:
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.