20TD02U Programmering av nullpunkt med halveringsmetoden_v2 - itnett/FTD02H-N GitHub Wiki

20TD02U Programmering av nullpunkt med halveringsmetoden_v2

Prøvd å rettett opp markdown og latex

20TD02U Programmering av nullpunkt med halveringsmetoden

Se også 00TD02A-Halveringsmetoden

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

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)

Forklaring av Forbedret Kode

  1. Generisk Funksjon:

    • Brukeren kan definere funksjonen f(x) i koden.
  2. Dynamisk Antall Iterasjoner:

    • Funksjonen bisection_method tar inn ønsket nøyaktighet tol og fortsetter å iterere til intervallet er mindre enn tol.
  3. Visualisering:

    • Funksjonen plot_function_and_root tegner grafen til funksjonen, markerer roten og viser midtpunktene brukt i iterasjonene.

Hvordan Kjøre Koden

  1. Kopier Koden:

    • Kopier hele koden over til din Python IDE eller en nettbasert Python-kjører som Trinket.io.
  2. Kjør Koden:

    • Kjør programmet og følg instruksjonene for å skrive inn nedre og øvre grense for intervallet, samt ønsket nøyaktighet.
  3. 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.

Forbedring av Koden for Bedre Brukervennlighet

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.

Forbedret Python-kode

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)

Forklaring av Forbedret Kode

  1. Input Validering:

    • Funksjonen get_valid_input sørger for at brukeren gir gyldige inndata ved å sjekke om a er mindre enn b og at f(a) og f(b) har motsatte fortegn. Hvis ikke, blir brukeren bedt om å prøve igjen.
  2. Hovedprogram:

    • Inputene blir samlet ved hjelp

av get_valid_input, og deretter blir bisection_method kalt med de validerte verdiene.

  1. Unntakshåndtering:
    • Hvis det oppstår en feil i bisection_method, vil feilmeldingen bli fanget og skrevet ut.

Dette sikrer at brukeren ikke kan skrive inn verdier som bryter forutsetningene for halveringsmetoden, og gir en mer robust og brukervennlig opplevelse.

Gyldige Verdier som Vil Gi Resultater

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

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

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

Ugyldige Verdier som Ikke Vil Gi Resultater

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

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

  3. 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.
⚠️ **GitHub.com Fallback** ⚠️