6.1 Numerisk derivasjon, integrasjon og nullpunkt
De korte numeriske byggeoppgavene: forlengs/sentrert differanse, trapesmetoden, og nullpunkt med Newton/secant + `scipy.optimize.root`.
Alle tre hører til sjanger N, som er samlebetegnelsen på de små numeriske byggeoppgavene: skriv en funksjon som regner ut noe tilnærmet, og bruk den.
- Numerisk derivasjon er i 4 av de 8 nyere settene (50 %), enten som en funksjon eller som en liten klasse. Prioritet: kunne (nivå 2 av tre: må sitte, kunne, kjenne til).
- Nullpunkt og likningsløsing — Newtons metode, sekantmetoden og biblioteksfunksjonen root — er i 3 av 8 sett (38 %), og andelen er voksende: de tre forekomstene ligger i de nyere settene. Prioritet: kjenne til (nivå 3), men det er nivå 3-stoffet som skiller toppkarakterene.
- Numerisk integrasjon (trapesmetoden) er bare i 1 av 8 sett (13 %), og da nesten bare som et flervalgsspørsmål om hva et kall gjør. Prioritet: kjenne til. Delkapitlet er derfor kort.
Vekten er 2 til 8 poeng. Det som gjør sjangeren verdt trening, er at formlene er tre linjer hver og gjentar seg nesten uendret — og at oppgaven ofte ber deg vise at metoden virker, altså sammenligne med det eksakte svaret. Det er nettopp det dette kapitlet driller: aldri et tilnærmet tall uten en sammenligning.
Sist du var her
Del 6 kommer et godt stykke inn i boka, så her er de tre tingene fra tidligere kapitler som dette kapitlet bygger rett på — friskt oppfrisket med kode.
1) En funksjon kan sendes inn som argument (kap. 1.6). Alle metodene i kapitlet tar funksjonen som skal behandles, som argument:
from math import sin
def verdi_i(f, x):
return f(x)
print(verdi_i(sin, 0.0))
print(verdi_i(lambda x: x**2 - 2, 3.0))Utskrift:
0.0
7.02) Default-argumenter (kap. 1.6). Steglengden får en fornuftig standardverdi, slik at den kan utelates i kallet:
def demo(x, h=1e-5):
return x + h
print(demo(1.0))
print(demo(1.0, 0.5))Utskrift:
1.00001
1.53) Testfunksjonen med toleranse (kap. 3.1). Aldri == på flyttall — alltid abs(...) < tol:
def test_kvadrat():
expected = 4.0
computed = 2.0**2
tol = 1e-10
assert abs(expected - computed) < tol, 'kvadrering feiler'
test_kvadrat()
print('testen passerte')Utskrift:
testen passerteForkunnskaper
- Funksjoner, default-argumenter og lambda: kap. 1.6.
- Løkker og while: kap. 1.3.
- NumPy-tabeller: kap. 4.1.
- Testfunksjoner: kap. 3.1.
- Klasser med __init__ og __call__: kap. 5.1, til den ene varianten der den deriverte pakkes i en klasse.
Matematikken bak metodene er ikke pensum her, men den ligger tilgjengelig hvis du vil se hvor formlene kommer fra: grensedefinisjonen av den deriverte i Deriverbarhet: grensedefinisjonen, summen bak trapesmetoden i Riemann-integralet og integrerbarhet, og Newtons metode i flere variable i Kontraksjon, fikspunkt og Newtons metode i flere variable. En mykere innføring på lavere nivå finnes i Numeriske metoder og programmering og Programmering av integrasjon.
Kapitlet er delt i tre løkker med tidsanslag.
Løkke 1 — den deriverte som differanse (~20 min)
En bevegelsessensor logger posisjonen til en isbre hver dag. Du vil vite hvor fort breen beveger seg, altså den deriverte av posisjonen — men du har bare tall, ingen formel å derivere.
Løsningen er den samme som definisjonen av den deriverte, bare uten grenseovergangen: regn stigningen mellom to punkter som ligger tett. Det gir to formler, og forskjellen mellom dem er hele poenget i dette delkapitlet.
Den deriverte i punktet er
Setter vi inn en liten, men endelig , får vi den forlengs differansen. Bruker vi i stedet punkter på hver side av , får vi den sentrerte differansen — og den er langt mer nøyaktig, som tallene straks skal vise.
med en liten, fast . Nevneren er h, og de to funksjonsverdiene er i x og x+h. Feilen er omtrent proporsjonal med : halverer du , halveres feilen. Metoden kalles førsteordens av samme grunn.
from math import sin, cos, pi
h = 1e-4
x = pi/3
print((sin(x+h) - sin(x))/h)
print(cos(x))Utskrift:
0.4999566978958203
0.5000000000000001med funksjonsverdier på hver side av . Nevneren er , ikke — det er den vanligste feilen i formelen. Feilen er omtrent proporsjonal med : tideler du , blir feilen hundre ganger mindre. Metoden er andreordens, og den er derfor standardvalget i faget når oppgaven ikke sier noe annet.
from math import sin, cos, pi
h = 1e-4
x = pi/3
print((sin(x+h) - sin(x-h))/(2*h))
print(cos(x))Utskrift:
0.49999999916616744
0.5000000000000001Bruk begge formlene på i punktet , der den eksakte deriverte er . Regn ut feilen for , og vis hvor mange ganger mindre feilen blir for hvert steg.
Et numerisk resultat uten sammenligning er halvt arbeid. Her har vi det eksakte svaret, så vi kan regne ut feilen direkte — og faktoren mellom radene forteller hvilken orden metoden har.
from math import sin, cos, pi
x = pi/3
eksakt = cos(x)
print(' h forlengs feil faktor')
forrige = 0.0
for k in range(1, 7):
h = 10.0**(-k)
d = (sin(x+h) - sin(x))/h
feil = abs(d - eksakt)
faktor = forrige/feil if forrige > 0 else 0.0
print(f'{h:8.0e} {d:12.8f} {feil:12.2e} {faktor:9.1f}')
forrige = feilUtskrift:
h forlengs feil faktor
1e-01 0.45590189 4.41e-02 0.0
1e-02 0.49566158 4.34e-03 10.2
1e-03 0.49956690 4.33e-04 10.0
1e-04 0.49995670 4.33e-05 10.0
1e-05 0.49999567 4.33e-06 10.0
1e-06 0.49999957 4.33e-07 10.0Faktoren er 10 hele veien: feilen skrumper like mye som h. Det er signaturen til en førsteordens metode.
Nå den sentrerte:
from math import sin, cos, pi
x = pi/3
eksakt = cos(x)
print(' h sentrert feil faktor')
forrige = 0.0
for k in range(1, 7):
h = 10.0**(-k)
d = (sin(x+h) - sin(x-h))/(2*h)
feil = abs(d - eksakt)
faktor = forrige/feil if forrige > 0 else 0.0
print(f'{h:8.0e} {d:12.8f} {feil:12.2e} {faktor:9.1f}')
forrige = feilUtskrift:
h sentrert feil faktor
1e-01 0.49916708 8.33e-04 0.0
1e-02 0.49999167 8.33e-06 100.0
1e-03 0.49999992 8.33e-08 100.0
1e-04 0.50000000 8.34e-10 99.9
1e-05 0.50000000 7.83e-12 106.5
1e-06 0.50000000 4.11e-11 0.2Faktoren er nær 100 for de første radene: feilen skrumper som . Med er den sentrerte formelen alt fem tierpotenser bedre enn den forlengse.
Men se på siste rad: faktoren faller til 0,2, altså feilen vokser når blir for liten. Det er ikke en trykkfeil, og det er ingen feil i koden — det er avrundingsfeil i flyttallene. Når og er nesten like, mister differansen mellom dem gyldige siffer, og til slutt dominerer den effekten. Derfor er h = 1e-5 bokas standardvalg: liten nok til å være nøyaktig, stor nok til at avrundingen ikke tar over.
1. Feil nevner. Forlengs differanse deler på h, sentrert deler på 2*h. Å bruke h i den sentrerte formelen halverer svaret — og halvparten av riktig svar ser ikke åpenbart galt ut, så feilen overlever ofte til innlevering.
2. h for liten. Med blir svaret verre, ikke bedre, av avrundingsgrunner (se konvergenstabellen over). Bruk h = 1e-5 som standard hvis oppgaven ikke sier noe.
3. Feil punkt. Sentrert differanse bruker x+h og x-h; blander du inn x selv, har du laget en tredje formel som ikke er noen av de to.
4. Import-feil — dette er feil #10 i feilkatalogen: import sqrt from math er ugyldig Python. Riktig er from math import sqrt. Feilen brukes som plantet feil i «finn feilen»-oppgaver.
Bokas standardform for den numeriske deriverte som funksjon: den tar funksjonen f som argument, punktet x, og en steglengde med standardverdi. Kroppen er én linje med den sentrerte formelen, og funksjonen returnerer ett tall.
from math import sin, pi
def diff(f, x, h=1e-5):
return (f(x+h) - f(x-h))/(2*h)
print(diff(sin, pi/3))
print(diff(lambda x: x**3, 2.0))Utskrift:
0.4999999999921733
12.00000000021184(Innstegsoppgave, sjanger N — numerisk byggeoppgave.) Funksjonen har den eksakte deriverte .
a) Skriv diff(f, x, h=1e-5) med sentrert differanse.
b) Hva blir diff(f, 3.0) omtrent, og hva er det eksakte svaret?
c) Hvorfor er svaret i b) nesten, men ikke helt, eksakt?
Samme formel pakket i en klasse, slik at instansen selv blir en funksjon: __init__ husker funksjonen og steglengden, og __call__ regner ut den deriverte i et punkt. Klasseapparatet står i kap. 5.1; her er poenget bare at eksamen har brukt begge formene, og at de gir samme tall.
En instans er ett konkret objekt laget av klassen, og en instans er kallbar når den kan brukes med parenteser som en funksjon — det er __call__ som gjør den kallbar.
from math import sin, pi
class Diff:
def __init__(self, f, h=1e-5):
self.f = f
self.h = h
def __call__(self, x):
f, h = self.f, self.h
return (f(x+h) - f(x-h))/(2*h)
dsin = Diff(sin)
print(dsin(pi/3))Utskrift:
0.4999999999921733Skriv diff(f, x, h=1e-5) med sentrert differanse, og en testfunksjon som kontrollerer den mot en funksjon du kjenner den eksakte deriverte til. Bruk toleransen .
Løkke 2 — trapesmetoden (~12 min)
— naturlig pausepunkt —
Motstykket til å derivere numerisk er å integrere numerisk: å regne ut arealet under en kurve når du bare har funksjonsverdier. Trapesmetoden deler intervallet i biter og erstatter kurven med en rett linje over hver bit, slik at hvert stykke blir et trapes.
Dette er lavfrekvent stoff (1 av 8 sett, 13 %), og da nesten bare som et flervalgsspørsmål om hva et kall gjør. Delkapitlet er derfor kort: én formel, én konvergenstabell, én oppgave.
Endepunktene teller halvt, alle de indre punktene teller helt. Legg merke til grensene i summen: range(1, N) — den går fra 1 til , altså bare de indre punktene. Feilen er proporsjonal med , så en dobling av firedobler nøyaktigheten.
def trapes(f, a, b, N):
dx = (b - a)/N
s = 0.5*f(a) + 0.5*f(b)
for k in range(1, N):
s += f(a + k*dx)
return s*dx
print(trapes(lambda x: x**2, 0.0, 1.0, 10))Utskrift:
0.3350000000000001Regn ut med trapesmetoden for . Det eksakte svaret er . Vis feilen og faktoren mellom radene.
Her kjenner vi svaret eksakt, så feilen kan regnes ut direkte.
def trapes(f, a, b, N):
dx = (b - a)/N
s = 0.5*f(a) + 0.5*f(b)
for k in range(1, N):
s += f(a + k*dx)
return s*dx
eksakt = 1/3
print(' N trapes feil faktor')
forrige = 0.0
for N in [5, 10, 20, 40, 80]:
T = trapes(lambda x: x**2, 0.0, 1.0, N)
feil = abs(T - eksakt)
faktor = forrige/feil if forrige > 0 else 0.0
print(f'{N:4d} {T:12.10f} {feil:12.3e} {faktor:8.2f}')
forrige = feilUtskrift:
N trapes feil faktor
5 0.3400000000 6.667e-03 0.00
10 0.3350000000 1.667e-03 4.00
20 0.3337500000 4.167e-04 4.00
40 0.3334375000 1.042e-04 4.00
80 0.3333593750 2.604e-05 4.00Faktoren er nøyaktig 4,00 for hver dobling av : feilen skrumper som . Det er slik du viser at en metode er andreordens uten å bevise noe — du dobler oppløsningen og ser at feilen firedeles.
Legg også merke til at alle tilnærmingene ligger over det eksakte svaret. Det er fordi krummer oppover, så et rett linjestykke mellom to punkter på kurven ligger over kurven, og trapeset blir litt for stort.
Trapesmetoden skal brukes på , der det eksakte svaret er 2.
a) Skriv trapes(f, a, b, N).
b) Hva blir tilnærmingen for og , og hvor stor er feilen i hvert tilfelle?
c) Stemmer faktoren mellom de to feilene med at metoden er andreordens?
Løkke 3 — finne nullpunkt (~23 min)
Nå til nivå 3-stoffet, det som skiller de beste besvarelsene. Oppgaven er: gitt en funksjon , finn et slik at .
Slike likninger dukker opp overalt i vitenskapelig programmering. Skal du finne likevektstemperaturen i en varmemodell, tidspunktet der to bestander er like store, eller den implisitte oppdateringen i baklengs Euler (kap. 7.4), er svaret et nullpunkt i en funksjon du ikke kan løse for hånd.
Tre verktøy dekker alt eksamen har spurt om: Newtons metode (krever den deriverte), sekantmetoden (krever den ikke), og root fra scipy.optimize (biblioteksfunksjonen, som dessuten takler systemer med flere ukjente).
Løkka kjører til funksjonsverdien er liten nok: while abs(f(x)) > eps:. Metoden er svært rask når startgjetningen er brukbar — antall riktige siffer omtrent dobles per runde. Den krever at du kan gi den deriverte som en egen funksjon, og den kan bomme helt hvis er nær null.
def newton(f, df, x, eps=1e-12):
while abs(f(x)) > eps:
x = x - f(x)/df(x)
return x
print(newton(lambda x: x**2 - 2, lambda x: 2*x, 1.0))Utskrift:
1.4142135623730951Finn den positive løsningen av med Newtons metode fra . Skriv ut hver runde, og sammenlign med sqrt(2) fra math.
Her kjenner vi svaret: . Da kan vi se hvordan feilen utvikler seg fra runde til runde.
from math import sqrt
def f(x):
return x**2 - 2
def df(x):
return 2*x
x = 1.0
n = 0
print('runde x feil')
while abs(f(x)) > 1e-12:
x = x - f(x)/df(x)
n += 1
print(f'{n:5d} {x:17.15f} {abs(x - sqrt(2)):15.3e}')
print('sqrt(2) fra math:', sqrt(2))Utskrift:
runde x feil
1 1.500000000000000 8.579e-02
2 1.416666666666667 2.453e-03
3 1.414215686274510 2.124e-06
4 1.414213562374690 1.595e-12
5 1.414213562373095 0.000e+00
sqrt(2) fra math: 1.4142135623730951Se på feilkolonnen: , , , . Antall riktige siffer dobles for hver runde — det kalles kvadratisk konvergens, og det er derfor Newtons metode trenger så få runder. Etter fem runder er svaret identisk med sqrt(2) til siste siffer.
Sammenlign med trapesmetoden, der en dobling av arbeidet ga fire ganger bedre svar. Her gir én ekstra runde kvadratet av forbedringen. Det er en helt annen skala.
1. Ingen stoppgrense på antall runder. while abs(f(x)) > eps: kan kjøre i det uendelige hvis metoden ikke nærmer seg noe — for eksempel om er nær null, eller om det ikke finnes noe nullpunkt. En sikring koster to linjer:
def newton(f, df, x, eps=1e-12, maks=100):
n = 0
while abs(f(x)) > eps and n < maks:
x = x - f(x)/df(x)
n += 1
return x2. eps for stram. Med eps = 1e-16 kan abs(f(x)) aldri komme under grensen på grunn av avrunding, og løkka går evig. 1e-10 til 1e-12 er trygt.
3. Å sende inn et uttrykk der en funksjon kreves — feil #19 i feilkatalogen. f = x**2 - 2 er et tall (eller en feilmelding om x ikke finnes); det som skal sendes inn er f = lambda x: x**2 - 2 eller en def-funksjon. Dette er en klassisk flervalgsfelle.
4. Feil fortegn i oppdateringen. Det skal være minus: x - f(x)/df(x). Med pluss beveger du deg bort fra nullpunktet.
Metoden trenger to startverdier og ingen derivert, og den er nesten like rask som Newton. Legg merke til at oppdateringen bare bruker de to siste verdiene — dette er samme mønster som en differenslikning (kap. 6.2), og det løses med en løkke som skyver verdiene videre.
def sekant(f, x0, x1, eps=1e-12, maks=100):
n = 0
while abs(f(x1)) > eps and n < maks:
x_ny = x1 - f(x1)*(x1 - x0)/(f(x1) - f(x0))
x0, x1 = x1, x_ny
n += 1
return x1
print(sekant(lambda x: x**2 - 2, 1.0, 2.0))Utskrift:
1.4142135623730954Sekantmetoden skal brukes på med startverdiene og .
a) Skriv sekant(f, x0, x1, eps=1e-12, maks=100).
b) Skriv ut hver runde med feilen mot sqrt(2), og si hvor mange runder som trengs.
c) Hvilken fordel har sekantmetoden framfor Newtons metode, og hvilken ulempe?
Biblioteksfunksjonen som løser , også når har flere komponenter. Tre ting må sitte:
- fun tar ett array-argument og returnerer ett array — én komponent per likning.
- Startgjetningen x0 er også et array.
- Løsningen ligger i sol.x, som er et array. sol.success sier om metoden lyktes.
Dokumentasjonen for root leveres alltid som vedlegg på eksamen, så du trenger ikke pugge signaturen — men du må kunne pakke funksjonen din riktig, altså array inn og array ut. Det er nettopp det oppgavene tester.
import numpy as np
from scipy.optimize import root
def fun(x):
return np.array([x[0]**2 - 2])
sol = root(fun, np.array([1.0]))
print(sol.x, sol.success)Utskrift:
[1.41421356] TrueDen vanligste feilen med root er å skrive funksjonen som om den tok og ga ett tall. Med én ukjent går det ofte likevel bra, fordi NumPy regner elementvis på et array med ett element — men med flere ukjente går det galt, og løsningen kommer alltid tilbake som et array, aldri som et tall.
Fast oppsett for to likninger og to ukjente:
import numpy as np
from scipy.optimize import root
def fun(v):
x, y = v
return np.array([x + y - 5.0, x*y - 6.0])
sol = root(fun, np.array([1.0, 4.0]))
print(sol.x)Utskrift:
[2. 3.]Legg merke til utpakkingen x, y = v på første linje i fun — det er mønsteret som gjør resten av funksjonen lesbar, og det samme mønsteret brukes i høyresiden til et ODE-system i kap. 7.3. Husk også at svaret er sol.x[0] og sol.x[1], ikke sol.x alene, når du skal bruke tallene videre.
To bestander utvikler seg slik at antallet er og . Du skal finne tidspunktet der de to er like store.
a) Sett opp funksjonen som skal ha nullpunkt.
b) Løs likningen med root, med startgjetning .
c) Kontroller svaret ved å regne ut begge bestandene i det tidspunktet du fant.
Programmet skal finne nullpunktet til med Newtons metode. Finn de tre feilene, og forklar hva hver av dem fører til.
import sqrt from math
def f(x):
return x**3 - 5
def df(x):
return 3*x
x = 1.0
while abs(f(x)) > 1e-16:
x = x + f(x)/df(x)
print(x)1. Nevner h der det skal være 2*h i sentrert differanse. Halvparten av riktig svar.
2. h for liten. Under tar avrundingsfeilene over, og svaret blir verre. Standard er 1e-5.
3. Feil summegrenser i trapesmetoden. Endepunktene halve, indre punkter hele, range(1, N).
4. Newton uten grense på antall runder, eller med for stram eps — uendelig løkke.
5. Feil fortegn i Newton-oppdateringen. Det skal være minus.
6. #19: uttrykk der funksjon kreves. g = x**2 - 2 mot g = lambda x: x**2 - 2.
7. #10: import-feil. from math import sqrt, from scipy.optimize import root — modulen først.
8. root uten array. fun tar ett array og returnerer ett array, og svaret er sol.x[0].
9. Tilnærmet svar uten sammenligning. Har oppgaven et eksakt svar tilgjengelig, skal du regne feilen. Har den ikke, halverer du steglengden og viser at svaret slutter å endre seg.
Begrepsbank
Begrepsbanken er flashcard-/repetisjonsstoff — den gjentar det du nettopp har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet gjelder kjernestoffet.
Eksamensoppgaven «skriv en kort funksjon som regner ut noe tilnærmet, og bruk den»: numerisk derivert, integral eller nullpunkt. Vekten er 2 til 8 poeng. Derivasjon er i 4 av 8 sett (50 %), nullpunkt i 3 av 8 (38 %, voksende), og integrasjon i 1 av 8 (13 %).
En førsteordens metode har feil omtrent proporsjonal med steglengden: halverer du steget, halveres feilen. En andreordens metode har feil proporsjonal med steget i annen: halverer du steget, blir feilen en firedel. Forlengs differanse er førsteordens, sentrert differanse og trapesmetoden er andreordens.
Standardmåten å vise at en metode virker: kjør den for flere steglengder, regn feilen mot det eksakte svaret, og se på faktoren mellom radene. Faktor 10 per tideling av betyr førsteordens, faktor 100 betyr andreordens. Har du ikke noe eksakt svar, halverer du steget og viser at svaret slutter å endre seg i de sifrene du bryr deg om.
Feilen i en differanseformel synker med h bare til et punkt. Når f(x+h) og f(x-h) blir nesten like, mister differansen gyldige siffer, og feilen begynner å vokse igjen. For sentrert differanse ligger vendepunktet rundt , og derfor er h = 1e-5 bokas standardvalg.
Standardverdien gjør at diff(f, x) kan kalles uten å oppgi steglengden, men at diff(f, x, 1e-3) fortsatt virker. Default-argumenter står etter de vanlige argumentene i signaturen. Merk feil #21 i feilkatalogen: en default-verdi må ikke være en liste eller annen muterbar verdi.
Endepunktene teller halvt, alle indre punkter helt, og hele summen ganges med . I kode: s = 0.5*f(a) + 0.5*f(b), deretter for k in range(1, N): s += f(a + k*dx), til slutt return s*dx. Grensen range(1, N) treffer nøyaktig de indre punktene.
x = x - f(x)/df(x), gjentatt til abs(f(x)) er under en toleranse. Krever den deriverte som egen funksjon, og konvergerer kvadratisk: antall riktige siffer dobles per runde. Feilen som ødelegger den er pluss i stedet for minus, eller manglende grense på antall runder.Newton uten derivert: linjen gjennom de to siste punktene brukes i stedet for tangenten. Trenger to startverdier, og oppdateringen er x1 - f(x1)*(x1 - x0)/(f(x1) - f(x0)). De to verdiene skyves videre med x0, x1 = x1, x_ny. Nesten like rask som Newton, og uunnværlig når den deriverte ikke finnes på formel.
while abs(f(x)) > eps sammen med en teller og en grense n < maks. Toleransen eps bør ligge mellom og : er den strammere, kan avrunding gjøre at den aldri nås, og løkka går evig. Grensen på antall runder er billig forsikring, og den nevnes eksplisitt i løsningsforslag.fun tar ett array-argument og returnerer ett array med én komponent per likning; x0 er også et array. sol = root(fun, x0) gir løsningen i sol.x (et array) og statusen i sol.success. Ett tall hentes med sol.x[0]. Dokumentasjonen leveres på eksamen, men innpakningen må du kunne selv.Skal du finne når , setter du opp differansen og finner nullpunktet til . Alle tre metodene i kapitlet gjør det samme med ; det eneste du gjør, er å sette opp differansen riktig.
Sett løsningen tilbake i den opprinnelige likningen og se om venstre side blir null (eller at de to størrelsene blir like). Dette er den eneste måten å oppdage at en løser har konvergert mot et annet nullpunkt enn du var ute etter, og det gir poeng i seg selv i løsningsforslag.
Alle metodene i kapitlet tar funksjonen som skal behandles, som argument: diff(f, x), trapes(f, a, b, N), newton(f, df, x). Da må du sende inn selve funksjonen (f, sin eller en lambda), ikke et funksjonskall og ikke et uttrykk. Å sende f(x) i stedet for f er å sende ett tall — en klassisk flervalgsfelle.
En grov metode krever slakk toleranse. Sentrert differanse med h = 1e-5 treffer på rundt , så tol = 1e-6 er trygt. Forlengs differanse med samme h treffer bare på rundt , og da vil tol = 1e-6 få testen til å feile selv om koden er riktig.
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.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Universitetet i Oslo. Dette er ikke offisielt studiemateriell. Les mer.