20TD02U Programmering av nullpunkt med halveringsmetoden_v2 - itnett/FTD02H-N GitHub Wiki
Prøvd å rettett opp markdown og latex
Se også 00TD02A-Halveringsmetoden
Halveringsmetoden (bisection method) er en numerisk metode for å finne røtter (nullpunkter) til en kontinuerlig funksjon. Metoden fungerer ved å gjentatte ganger dele intervallet i to og velge det delintervallet hvor funksjonen skifter fortegn. Dette garanterer at intervallet som inneholder roten halveres for hver iterasjon, og vi konvergerer mot en rot med ønsket nøyaktighet.
Her er en forbedret versjon av koden som inkluderer følgende:
- Generisk funksjon: Brukeren kan skrive inn en hvilken som helst funksjon.
- Dynamisk antall iterasjoner: Koden vil fortsette å iterere til ønsket nøyaktighet er nådd.
- Visualisering: Koden vil tegne grafen til funksjonen og markere nullpunktet.
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return (1/3)*x**3 + (1/2)*x**2 - x - 1
def bisection_method(f, a, b, tol=0.0001):
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have opposite signs")
midpoints = []
while (b - a) / 2 > tol:
midpoint = (a + b) / 2
midpoints.append(midpoint)
if f(midpoint) == 0:
return midpoint, midpoints
elif f(a) * f(midpoint) < 0:
b = midpoint
else:
a = midpoint
return (a + b) / 2, midpoints
def plot_function_and_root(f, a, b, root, midpoints):
x = np.linspace(a, b, 400)
y = f(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='f(x) = (1/3)*x^3 + (1/2)*x^2 - x - 1')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.plot(root, f(root), 'ro', label=f'Root ≈ {root:.4f}')
for i, m in enumerate(midpoints):
plt.plot([a, b], [f(a), f(b)], 'g:')
plt.plot([m, m], [0, f(m)], 'b:')
plt.text(m, f(m) + 0.1, f'm{i+1}', ha='center')
plt.title('Bisection Method')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True)
plt.show()
# Input from user
a = float(input("Skriv inn nedre grense i dette intervallet: "))
b = float(input("Skriv inn øvre grense i dette intervallet: "))
tol = float(input("Skriv inn ønsket nøyaktighet (f.eks. 0.0001): "))
try:
root, midpoints = bisection_method(f, a, b, tol)
print(f"Nullpunktet er x ≈ {root:.4f}")
plot_function_and_root(f, a, b, root, midpoints)
except ValueError as e:
print(e)
Her er hele artikkelen optimalisert for markdown som en kodeblokk:
```markdown
# 20TD02U Programmering av nullpunkt med halveringsmetoden
Se også [00TD02A-Halveringsmetoden](https://github.com/itnett/FTD02H-N/wiki/00TD02A-Halveringsmetoden-Steg%E2%80%90for%E2%80%90steg-Forklaring)
### Forklaring av Halveringsmetoden
Halveringsmetoden (bisection method) er en numerisk metode for å finne røtter (nullpunkter) til en kontinuerlig funksjon. Metoden fungerer ved å gjentatte ganger dele intervallet i to og velge det delintervallet hvor funksjonen skifter fortegn. Dette garanterer at intervallet som inneholder roten halveres for hver iterasjon, og vi konvergerer mot en rot med ønsket nøyaktighet.
### Forbedret Algoritme og Kode
Her er en forbedret versjon av koden som inkluderer følgende:
1. **Generisk funksjon:** Brukeren kan skrive inn en hvilken som helst funksjon.
2. **Dynamisk antall iterasjoner:** Koden vil fortsette å iterere til ønsket nøyaktighet er nådd.
3. **Visualisering:** Koden vil tegne grafen til funksjonen og markere nullpunktet.
### Forbedret Python-kode
```python
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return (1/3)*x**3 + (1/2)*x**2 - x - 1
def bisection_method(f, a, b, tol=0.0001):
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have opposite signs")
midpoints = []
while (b - a) / 2 > tol:
midpoint = (a + b) / 2
midpoints.append(midpoint)
if f(midpoint) == 0:
return midpoint, midpoints
elif f(a) * f(midpoint) < 0:
b = midpoint
else:
a = midpoint
return (a + b) / 2, midpoints
def plot_function_and_root(f, a, b, root, midpoints):
x = np.linspace(a, b, 400)
y = f(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='f(x) = (1/3)*x^3 + (1/2)*x^2 - x - 1')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.plot(root, f(root), 'ro', label=f'Root ≈ {root:.4f}')
for i, m in enumerate(midpoints):
plt.plot([a, b], [f(a), f(b)], 'g:')
plt.plot([m, m], [0, f(m)], 'b:')
plt.text(m, f(m) + 0.1, f'm{i+1}', ha='center')
plt.title('Bisection Method')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True)
plt.show()
# Input from user
a = float(input("Skriv inn nedre grense i dette intervallet: "))
b = float(input("Skriv inn øvre grense i dette intervallet: "))
tol = float(input("Skriv inn ønsket nøyaktighet (f.eks. 0.0001): "))
try:
root, midpoints = bisection_method(f, a, b, tol)
print(f"Nullpunktet er x ≈ {root:.4f}")
plot_function_and_root(f, a, b, root, midpoints)
except ValueError as e:
print(e)
-
Generisk Funksjon:
- Brukeren kan definere funksjonen
f(x)
i koden.
- Brukeren kan definere funksjonen
-
Dynamisk Antall Iterasjoner:
- Funksjonen
bisection_method
tar inn ønsket nøyaktighettol
og fortsetter å iterere til intervallet er mindre enntol
.
- Funksjonen
-
Visualisering:
- Funksjonen
plot_function_and_root
tegner grafen til funksjonen, markerer roten og viser midtpunktene brukt i iterasjonene.
- Funksjonen
-
Kopier Koden:
- Kopier hele koden over til din Python IDE eller en nettbasert Python-kjører som Trinket.io.
-
Kjør Koden:
- Kjør programmet og følg instruksjonene for å skrive inn nedre og øvre grense for intervallet, samt ønsket nøyaktighet.
-
Se Resultatet:
- Programmet vil beregne nullpunktet og vise grafen med nullpunktet og iterasjonstrinnene.
Dette programmet gir en klar og visuell fremstilling av halveringsmetoden, som gjør det lettere å forstå prosessen og verifisere resultatene.
Vi kan forbedre koden ved å legge til sjekk for at a
er mindre enn b
og at funksjonsverdiene f(a)
og f(b)
har motsatte fortegn. Vi vil også tillate brukeren å prøve igjen hvis inputene ikke oppfyller kravene.
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return (1/3)*x**3 + (1/2)*x**2 - x - 1
def bisection_method(f, a, b, tol=0.0001):
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have opposite signs")
midpoints = []
while (b - a) / 2 > tol:
midpoint = (a + b) / 2
midpoints.append(midpoint)
if f(midpoint) == 0:
return midpoint, midpoints
elif f(a) * f(midpoint) < 0:
b = midpoint
else:
a = midpoint
return (a + b) / 2, midpoints
def plot_function_and_root(f, a, b, root, midpoints):
x = np.linspace(a, b, 400)
y = f(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='f(x) = (1/3)*x^3 + (1/2)*x^2 - x - 1')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.plot(root, f(root), 'ro', label=f'Root ≈ {root:.4f}')
for i, m in enumerate(midpoints):
plt.plot([a, b], [f(a), f(b)], 'g:')
plt.plot([m, m], [0, f(m)], 'b:')
plt.text(m, f(m) + 0.1, f'm{i+1}', ha='center')
plt.title('Bisection Method')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True)
plt.show()
def get_valid_input():
while True:
try:
a = float(input("Skriv inn nedre grense i dette intervallet: "))
b = float(input("Skriv inn øvre grense i dette intervallet: "))
if a >= b:
print("Nedre grense må være mindre enn øvre grense. Prøv igjen.")
continue
tol = float(input("Skriv inn ønsket nøyaktighet (f.eks. 0.0001): "))
if f(a) * f(b) >= 0:
print("f(a) og f(b) må ha motsatte fortegn. Prøv igjen.")
continue
return a, b, tol
except ValueError as e:
print(f"Ugyldig inndata: {e}. Prøv igjen.")
# Hovedprogram
a, b, tol = get_valid_input()
try:
root, midpoints = bisection_method(f, a, b, tol)
print(f"Nullpunktet er x ≈ {root:.4f}")
plot_function_and_root(f, a, b, root, midpoints)
except ValueError as e:
print(e)
-
Input Validering:
- Funksjonen
get_valid_input
sørger for at brukeren gir gyldige inndata ved å sjekke oma
er mindre ennb
og atf(a)
ogf(b)
har motsatte fortegn. Hvis ikke, blir brukeren bedt om å prøve igjen.
- Funksjonen
-
Hovedprogram:
- Inputene blir samlet ved hjelp
av get_valid_input
, og deretter blir bisection_method
kalt med de validerte verdiene.
-
Unntakshåndtering:
- Hvis det oppstår en feil i
bisection_method
, vil feilmeldingen bli fanget og skrevet ut.
- Hvis det oppstår en feil i
Dette sikrer at brukeren ikke kan skrive inn verdier som bryter forutsetningene for halveringsmetoden, og gir en mer robust og brukervennlig opplevelse.
-
Intervall med motsatte fortegn:
$a = 0$, $b = 2$
$$ f(0) = -1 $$ $$ f(2) = \frac{1}{3} \cdot 2^3 + \frac{1}{2} \cdot 2^2 - 2 - 1 = 2.6667 + 2 - 2 - 1 = 1.6667 $$ Siden
$f(0)$ og$f(2)$ har motsatte fortegn, vil dette intervallet gi et resultat. -
Intervall med røtter innenfor området:
$a = -2$, $b = 0$
$$ f(-2) = \frac{1}{3} \cdot (-2)^3 + \frac{1}{2} \cdot (-2)^2 - (-2) - 1 = -2.6667 + 2 + 2 - 1 = 0.3333 $$ $$ f(0) = -1 $$ Siden
$f(-2)$ og$f(0)$ har motsatte fortegn, vil dette intervallet gi et resultat. -
Intervall med høyere nøyaktighet:
$a = 1$, $b = 2$, $tol = 0.00001$
$$ f(1) = \frac{1}{3} \cdot 1^3 + \frac{1}{2} \cdot 1^2 - 1 - 1 = 0.8333 - 1 - 1 = -1.1667 $$ $$ f(2) = 1.6667 $$ Siden
$f(1)$ og$f(2)$ har motsatte fortegn, vil dette intervallet gi et resultat, men med høyere nøyaktighet.
-
Intervall uten motsatte fortegn:
$a = 0$, $b = 1$
$$ f(0) = -1 $$ $$ f(1) = \frac{1}{3} \cdot 1^3 + \frac{1}{2} \cdot 1^2 - 1 - 1 = 0.8333 - 1 - 1 = -1.1667 $$ Siden både
$f(0)$ og$f(1)$ har negative verdier, vil dette intervallet ikke gi et resultat. -
Intervall med samme fortegn:
$a = -1$, $b = 1$
$$ f(-1) = \frac{1}{3} \cdot (-1)^3 + \frac{1}{2} \cdot (-1)^2 - (-1) - 1 = -0.3333 + 0.5 + 1 - 1 = 0.1667 $$ $$ f(1) = -1.1667 $$ Selv om
$f(-1)$ er positiv og$f(1)$ er negativ, vil dette intervallet kunne være gyldig. Men hvis vi endrer$b$ til 0, vil$f(-1)$ og$f(0)$ ikke ha motsatte fortegn, og intervallet vil ikke gi et resultat. -
Feil rekkefølge på grensene:
$a = 3$, $b = 2$
Grensene er i feil rekkefølge,
$a$ må være mindre enn$b$ . Dette vil ikke gi et resultat uansett funksjonsverdier.
Kode for å teste ulike intervaller
import matplotlib.pyplot as plt
import numpy as np
def f(x):
return (1/3)*x**3 + (1/2)*x**2 - x - 1
def bisection_method(f, a, b, tol=0.0001):
if f(a) * f(b) >= 0:
raise ValueError("f(a) and f(b) must have opposite signs")
midpoints = []
while (b - a) / 2 > tol:
midpoint = (a + b) / 2
midpoints.append(midpoint)
if f(midpoint) == 0:
return midpoint, midpoints
elif f(a) * f(midpoint) < 0:
b = midpoint
else:
a = midpoint
return (a + b) / 2, midpoints
def plot_function_and_root(f, a, b, root, midpoints):
x = np.linspace(a, b, 400)
y = f(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, label='f(x) = (1/3)*x^3 + (1/2)*x^2 - x - 1')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.plot(root, f(root), 'ro', label=f'Root ≈ {root:.4f}')
for i, m in enumerate(midpoints):
plt.plot([a, b], [f(a), f(b)], 'g:')
plt.plot([m, m], [0, f(m)], 'b:')
plt.text(m, f(m) + 0.1, f'm{i+1}', ha='center')
plt.title('Bisection Method')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True)
plt.show()
def test_intervals():
test_cases = [
(0, 2), # Gyldig
(-2, 0), # Gyldig
(1, 2), # Gyldig, høyere nøyaktighet
(0, 1), # Ugyldig, samme fortegn
(-1, 0), # Ugyldig, samme fortegn
(3, 2) # Ugyldig, feil rekkefølge
]
for a, b in test_cases:
try:
print(f"Testing interval ({a}, {b})")
root, midpoints = bisection_method(f, a, b)
print(f"Nullpunktet er x ≈ {root:.4f}\n")
except ValueError as e:
print(f"Feil for intervallet ({a}, {b}): {e}\n")
test_intervals()
Dette gir en klar og visuell fremstilling av hvilke intervaller som fungerer og hvilke som ikke gjør det, samt hvorfor de ikke fungerer. Ved å kjøre koden kan du se hvordan funksjonen reagerer på ulike inputverdier.
Denne formatert markdown-blokken kan nå kopieres og limes inn direkte for å beholde all formatering korrekt.