9.3

9.3 Programmering med følger og rekker

Python-implementasjon av følger og rekker, iterasjon og visualisering.

50 min
12 oppgaver
PythonFor-løkkerKonvergensMatplotlibVisualisering
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 12 oppgaver
Kapitlets plass i kurset

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 10−610^{-6}")

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.

✏️Sporingstabell for en while-løkke
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)

nnaaa>100a > 100?
0200200ja
10,8⋅200+10=1700{,}8 \cdot 200 + 10 = 170ja
20,8⋅170+10=1460{,}8 \cdot 170 + 10 = 146ja
30,8⋅146+10=126,80{,}8 \cdot 146 + 10 = 126{,}8ja
40,8⋅126,8+10=111,440{,}8 \cdot 126{,}8 + 10 = 111{,}44ja
50,8⋅111,44+10=99,1520{,}8 \cdot 111{,}44 + 10 = 99{,}152nei

Løkka stopper etter runde 5.
Svar: Programmet skriver ut 5 99.15.
b)
Programmet regner ut leddene i følgen a0=200a_0 = 200, an=0,8 an−1+10a_n = 0{,}8\,a_{n-1} + 10 til et ledd er 100 eller mindre.
Svar: Programmet finner at a5≈99,15a_5 \approx 99{,}15 er det første leddet som ikke er større enn 100.

Eksplisitte følger beregnes direkte:

# 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
# = 50

Delsummer 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.

✏️Lånamortisering med Python

Du tar opp et lån på 500 000 kr med 5 % nominell årlig rente. Du betaler 35 000 kr per år. La ana_n være restgjelden etter nn år.

a) Sett opp en rekursiv formel for ana_n.
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).

a) Rekursiv formel:

an+1=an⋅1,05−35 000,a0=500 000a_{n+1} = a_n \cdot 1{,}05 - 35\,000, \quad a_0 = 500\,000

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 0,05⋅an0{,}05 \cdot a_n er større enn betalingen på 35 000 kr, altså dersom an>700 000a_n > 700\,000 kr. Siden 500 000<700 000500\,000 < 700\,000, synker gjelden hvert år.

Eksplisitt formel: an=700 000−200 000⋅1,05na_n = 700\,000 - 200\,000 \cdot 1{,}05^n. Da gir an≤0a_n \leq 0 at 1,05n≥3,51{,}05^n \geq 3{,}5, altså n≥ln⁡3,5ln⁡1,05≈25,7\displaystyle n \geq \frac{\ln 3{,}5}{\ln 1{,}05} \approx 25{,}7.

Svar: a) an+1=1,05⋅an−35 000a_{n+1} = 1{,}05 \cdot a_n - 35\,000 med a0=500 000a_0 = 500\,000. c) Lånet er nedbetalt i løpet av år 26.

✏️Numerisk utforsking av konvergens

Bruk Python til å undersøke konvergensen av rekken ∑n=1∞1np\displaystyle \sum_{n=1}^{\infty} \frac{1}{n^p} for ulike verdier av pp.

a) Beregn delsummen S10 000S_{10\,000} for p=0,5p = 0{,}5, p=1p = 1, p=1,5p = 1{,}5 og p=2p = 2.
b) Plott delsummene som funksjon av NN for disse fire verdiene av pp.
c) Kommenter hvilke verdier av pp som gir konvergens.

a) og b) Python-program:

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:
- p=0,5p = 0{,}5: S10 000≈198,5S_{10\,000} \approx 198{,}5 (divergerer)
- p=1p = 1: S10 000≈9,79S_{10\,000} \approx 9{,}79 (divergerer, men sakte)
- p=1,5p = 1{,}5: S10 000≈2,592S_{10\,000} \approx 2{,}592 (konvergerer langsomt mot ζ(1,5)≈2,612\zeta(1{,}5) \approx 2{,}612)
- p=2p = 2: S10 000≈1,6448S_{10\,000} \approx 1{,}6448 (konvergerer mot π2/6≈1,6449\pi^2/6 \approx 1{,}6449)

Svar: c) Rekken ∑1/np\sum 1/n^p konvergerer når p>1p > 1 og divergerer når p≤1p \leq 1.

✏️Populasjonsmodell med logistisk vekst
En populasjon modelleres med den logistiske rekursive formelen
Pn+1=Pn+r⋅Pn(1−PnK)P_{n+1} = P_n + r \cdot P_n \left(1 - \frac{P_n}{K}\right)

der r=0,8r = 0{,}8 er vekstraten og K=1000K = 1000 er bæreevnen. Startpopulasjonen er P0=100P_0 = 100.

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 r=1,8r = 1{,}8. Hvordan endrer forløpet seg?

a) Python-program:

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 P0=100P_0 = 100, P1=172,0P_1 = 172{,}0, P2=285,9P_2 = 285{,}9, P3=449,3P_3 = 449{,}3, P4=647,2P_4 = 647{,}2, P5=829,9P_5 = 829{,}9, P6=942,8P_6 = 942{,}8, P7=985,9P_7 = 985{,}9, P8=997,0P_8 = 997{,}0, P9=999,4P_9 = 999{,}4 og P10=999,9P_{10} = 999{,}9.

Likevekt: P∗=P∗+rP∗(1−P∗K)\displaystyle P^* = P^* + rP^*\left(1 - \frac{P^*}{K}\right) gir rP∗(1−P∗K)=0\displaystyle rP^*\left(1 - \frac{P^*}{K}\right) = 0, altså P∗=0P^* = 0 eller P∗=KP^* = K.

Populasjonen vokser først nesten eksponentielt, så bremser veksten, og følgen nærmer seg bæreevnen K=1000K = 1000 uten å gå over.

c) r=1,8r = 1{,}8:

Programmet gir P1=262,0P_1 = 262{,}0, P2=610,0P_2 = 610{,}0, P3=1038,2P_3 = 1038{,}2, P4=966,8P_4 = 966{,}8, P5=1024,6P_5 = 1024{,}6 og P6=979,2P_6 = 979{,}2.

Populasjonen går over bæreevnen og svinger rundt 1000 med stadig mindre utslag. For 0<r<20 < r < 2 nærmer følgen seg KK.

Svar: b) Populasjonen nærmer seg bæreevnen K=1000K = 1000. c) Med r=1,8r = 1{,}8 svinger populasjonen rundt 1000 med avtagende utslag, men nærmer seg fortsatt 1000.

📝Oppgave 1

Grunnleggende programmering av følger

a

Skriv et Python-program som bruker en for-løkke til å skrive ut de 15 første leddene i den aritmetiske følgen an=7+4(n−1)a_n = 7 + 4(n-1) og beregner summen S15S_{15}. Verifiser summen analytisk med formelen Sn=n2(2a1+(n−1)d)\displaystyle S_n = \frac{n}{2}(2a_1 + (n-1)d).

b

Skriv et Python-program som genererer de 20 første leddene i den rekursive følgen a1=1000a_1 = 1000, an+1=0,85⋅ana_{n+1} = 0{,}85 \cdot a_n og plotter dem med matplotlib. Legg inn en stiplet linje for grenseverdien.

c

Bruk en while-løkke til å finne det første leddet i følgen an=1000⋅0,85n−1a_n = 1000 \cdot 0{,}85^{n-1} som er mindre enn 11.

Løs oppgaven
📝Oppgave 2

Delsummer og konvergens

a

Skriv et Python-program som beregner delsummene SN=∑n=1N1n3\displaystyle S_N = \sum_{n=1}^{N} \frac{1}{n^3} for N=10,100,1000,10 000N = 10, 100, 1000, 10\,000. Sammenlign med Aperys konstant ζ(3)≈1,202056903\zeta(3) \approx 1{,}202056903.

b

Plott delsummene Sn=∑k=1n(−1)k+1k\displaystyle S_n = \sum_{k=1}^{n} \frac{(-1)^{k+1}}{k} for n=1,2,…,200n = 1, 2, \ldots, 200 (den alternerende harmoniske rekken). Hva er grenseverdien?

Løs oppgaven
📝Oppgave 3

Figurtall med programmering

a

Skriv et Python-program som beregner og plotter de 20 første trekantallene Tn=n(n+1)2\displaystyle T_n = \frac{n(n+1)}{2} og de 20 første kvadrattallene Kn=n2K_n = n^2 i samme figur.

b

Verifiser med Python at Tn+Tn−1=n2T_n + T_{n-1} = n^2 for n=2,3,…,100n = 2, 3, \ldots, 100 ved å sjekke at differansen er null for alle nn.

📝Oppgave 4

Praktisk modellering og tilnærminger

a

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.

b

Skriv et Python-program som bruker Newtons metode (an+1=12(an+can)\displaystyle a_{n+1} = \frac{1}{2}(a_n + \frac{c}{a_n})) til å beregne c\sqrt{c} for c=7c = 7. Start med a0=3a_0 = 3 og kjør til ∣an+1−an∣<10−12|a_{n+1} - a_n| < 10^{-12}. Skriv ut hvert ledd og antall korrekte desimaler.

c

Bruk Python til å estimere π\pi ved hjelp av Leibniz-formelen: π4=1−13+15−17+⋯\displaystyle \frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \frac{1}{7} + \cdots. Plott feilen ∣Sn⋅4−π∣|S_n \cdot 4 - \pi| som funksjon av nn i logaritmisk skala. Hvor mange ledd trenger du for 6 korrekte desimaler?

📝Oppgave 5

Se på programmet.

S = 0
for n in range(1, 6):
    S = S + 3*n + 1
print(S)

a

Lag en sporingstabell og finn hva programmet skriver ut.

b

Forklar hva programmet regner ut.

Løs oppgaven
📝Oppgave 6

Se på programmet.

S = 0
n = 0
while S < 1000:
    n = n + 1
    S = S + 3*n + 1
print(n, S)

a

Forklar hva programmet finner ut.

b

Summen av de nn første leddene er Sn=n(3n+5)2S_n = \dfrac{n(3n + 5)}{2}. Bruk dette til å finne hva programmet skriver ut.

Løs oppgaven
📝Oppgave 7

Se på programmet.

saldo = 10000
ar = 0
while saldo < 20000:
    saldo = saldo * 1.05 + 1000
    ar = ar + 1
print(ar, round(saldo))

a

Forklar hva programmet regner ut.

b

Lag en sporingstabell og finn hva programmet skriver ut.

Løs oppgaven

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 SNS_N beregnes ved å akkumulere ledd i en sumvariabel — og kan brukes til å utforske konvergens numerisk.
- Numeriske metoder som Newtons metode (an+1=12(an+can)\displaystyle a_{n+1} = \frac{1}{2}(a_n + \frac{c}{a_n}) for c\sqrt{c}) er rekursive følger som konvergerer raskt.
- Leibniz-rekken π4=1−13+15−⋯\displaystyle \frac{\pi}{4} = 1 - \frac{1}{3} + \frac{1}{5} - \cdots konvergerer svært langsomt — valg av algoritme betyr mye.

NøkkelbegrepForklaring
For-løkkeGjentar et kjent antall ganger
While-løkkeGjentar til en betingelse brytes
AkkumulatorVariabel som samler opp en sum
Newtons metodeRekursiv tilnærming til røtter/nullpunkter
KonvergenshastighetHvor raskt en metode nærmer seg svaret

Viktige formler:
an+1=12(an+can)→c,π4=∑k=0∞(−1)k2k+1a_{n+1} = \tfrac{1}{2}\Big(a_n + \tfrac{c}{a_n}\Big) \to \sqrt{c}, \qquad \frac{\pi}{4} = \sum_{k=0}^{\infty}\frac{(-1)^k}{2k+1}
Repetisjonsoppgaver
Din fremgang
0deloppgaver0 / 5 oppgaver

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.