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

20TD02U Programmering av nullpunkt med halveringsmetoden

Se også 00TD02A-Halveringsmetoden

[python]

La oss starte med å forklare den originale oppgaven, deretter forbedre koden for å gjøre den mer generell og brukervennlig, og til slutt inkludere muligheten til å tegne grafen og markere nullpunktet.

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)

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.

[python]

Feilmeldingen "f(a) and f(b) must have opposite signs" indikerer at verdiene av funksjonen f ved grensene a og b ikke har motsatte fortegn. Dette er en forutsetning for halveringsmetoden, siden det sikrer at det er et nullpunkt mellom a og b.

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

[python]

La oss gå gjennom forskjellige verdier for parametrene og forklare hvilke vil gi resultater og hvilke som ikke vil gi resultater.

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 )
      • ( f(0) ) og ( f(2) ) har motsatte fortegn, så dette intervallet vil 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 )
      • ( f(-2) ) og ( f(0) ) har motsatte fortegn, så dette intervallet vil 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 )
      • ( f(1) ) og ( f(2) ) har motsatte fortegn, så dette intervallet vil 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 )
      • ( f(0) ) og ( f(1) ) har begge negative verdier, så dette intervallet vil 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 )
      • ( f(-1) ) er positiv og ( f(1) ) er negativ, så dette intervallet kan 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.

Eksempel på Testing i Kode

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()

Forklaring av Kode

  1. Definere Testtilfeller:

    • Vi har definert en liste med testtilfeller som inkluderer både gyldige og ugyldige intervaller.
  2. Teste Intervallene:

    • For hvert intervall prøver vi å kjøre bisection_method og fanger opp eventuelle feil med en try-except blokk.
  3. Resultat:

    • For gyldige intervaller vil funksjonen finne nullpunktet og skrive ut resultatet.
    • For ugyldige intervaller vil funksjonen skrive ut en feilmelding som forklarer hvorfor intervallet er ugyldig.

Kjør denne koden for å se hvilke intervaller som fungerer og hvilke som ikke gjør det, og forstå hvorfor ved å lese feilmeldingene.

Selvfølgelig! Her er informasjonen formatert på en måte som vil se bra ut på din GitHub Wiki-side.


Ulike Verdier for Halveringsmetoden

Her er en oversikt over ulike verdier for parametrene til halveringsmetoden, som både vil resultere i gyldige og ugyldige intervaller. Dette hjelper med å forstå hvorfor visse verdier fungerer mens andre ikke gjør det.

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 = 0$

    $$ 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(0) = -1 $$ Selv om $f(-1)$ er positiv og $f(0)$ 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.

Jeg forstår. La oss formatere informasjonen slik at den passer inn på en GitHub Wiki-side med matematiske utskrifter ved hjelp av LaTeX. Jeg vil også inkludere sammenleggbar innhold for ekstra detaljer.

Ulike Verdier for Halveringsmetoden

Her er en oversikt over ulike verdier for parametrene til halveringsmetoden, som både vil resultere i gyldige og ugyldige intervaller. Dette hjelper med å forstå hvorfor visse verdier fungerer mens andre ikke gjør det.

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 = 0$

    $$ 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(0) = -1 $$ Selv om $f(-1)$ er positiv og $f(0)$ 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.


Matematiske Utskrifter med LaTeX

Inline formel:

$a^2 + b^2 = c^2$

$a^2 + b^2 = c^2$

Blokk formel:

$$
\int_{a}^{b} x^2 \, dx
$$

$$ \int_{a}^{b} x^2 , dx $$


Matematiske Utskrifter med LaTeX

Inline formel:

$a^2 + b^2 = c^2$

$a^2 + b^2 = c^2$

Blokk formel:

$$
\int_{a}^{b} x^2 \, dx
$$

$$ \int_{a}^{b} x^2 , dx $$

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)

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.

  1. hovedprogram:

    • inputene blir samlet ved hjelp av get_valid_input, og deretter blir bisection_method kalt med de validerte verdiene.
  2. 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.

eksempel på testing i kode

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()

forklaring av kode

  1. definere testtilfeller:

    • vi har definert en liste med testtilfeller som inkluderer både gyldige og ugyldige intervaller.
  2. teste intervallene:

    • for hvert intervall prøver vi å kjøre bisection_method og fanger opp eventuelle feil med en try-except blokk.
  3. resultat:

    • for gyldige intervaller vil funksjonen finne nullpunktet og skrive ut resultatet.
    • for ugyldige intervaller vil funksjonen skrive ut en feilmelding som forklarer hvorfor intervallet er ugyldig.

kjør denne koden for å se hvilke intervaller som fungerer og hvilke som ikke gjør det, og forstå hvorfor ved å lese feilmeldingene.

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 Value

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

⚠️ **GitHub.com Fallback** ⚠️