Numerik: Integrale einer eindimensionalen Funktion

  • Dieser Thread ist für die Freunde der Numerik gedacht.
    Ich habe hier mal verschiedene numerische Integrationsmethoden implementiert und zum Vergleich gegenübergestellt.
    Implementiert sind Die Mittelpunkt-, Trapez-, Tangententrapez-, Simpson-, Gaußregel, die doppelt-exponentielle Methode, die Monte-Carlo-Methode, sowie die Romberg-Integration.
    Zusätzlich noch eine kleine Funktion zur Berechnung eines Kurvenintegrals.
    Um eine gewünschte Integrationsgenauigkeit sicherzustellen gibt es eine Funktion namens _MathInt_IntAccurate welche die Genauigkeit iterativ prüft (außer für die Monte-Carlo-Methode (da versagt der Ansatz) und die Romberg-Integration (da ist die Genauigkeitsschätzung schon drin)).

    Natürlich kann man das ganze auch produktiv einsetzen.
    Für den Fall empfehle ich vor allem die Romberg-Integration - die erreicht die geforderte Genauigkeit verdammt fix.
    Um das ganze auch flexibel zu verwenden, kann man seine zu integrierende Funktion entweder als String (z.B. "sin(x)") oder als AutoIt-Funktion angeben).

    Genug zur Einstimmung - hier das Skript:

    Numerische 1D-Integration mit festgelegter Genauigkeit - Algorithmenvergleich
    [autoit]

    ; eine benutzerdefinierte Funktion mit einem Parameter und einer reelen Zahl als Rückgabewert (=1D-Funktion):
    Func MyFunc(Const $x)
    Return Sin($x)
    EndFunc ;==>MyFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; zu integrierende Funktion als Variable - entweder eine Funktionsvariable oder eine String
    Global Const $IntFunction = MyFunc ; Entweder ein String (z.B: $IntFunction="sin(x)+2") oder eine Funktionsvariable (z.B. $IntFunction = MyFunc oder $IntFunction = Cos)

    [/autoit] [autoit][/autoit] [autoit]

    ; Integralgrenzen:
    Global Const $a = 0
    Global Const $b = ACos(-1) ; = Pi

    [/autoit] [autoit][/autoit] [autoit]

    ; zu erreichende Genauigkeit (nur bei Funktionen welche dies ermöglichen)
    Global Const $EPS = 10E-5

    [/autoit] [autoit][/autoit] [autoit]

    Global $n = 10 ; Anzahl an Wiederholungen für die Zeitmessung
    Global $d_Steps = 256 ; Anzahl der Teilintervalle für die Monte-Carlo-Regel
    Global $f_RealValue = 2.0 ; der bekannte wahre Integrationswert (für Genauigkeitsvergleich)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Vergleich der verschiedenen Algorithmen bezüglich Genauigkeit und Geschwindigkeit
    ConsoleWrite(StringFormat("\n------------------ Flächenintegrale ------------------\n"))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Romberg-Integration
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_Romberg($IntFunction, $a, $b, $EPS)
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Romberg-Integration", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die doppelt-exponentielle Methode
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "DoubleExponential")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Doppelt-Exponentiell", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Gauss-Regel
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "Gauss")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Gaußregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Simpson-Regel
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "Simpson")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Simpsonregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Trapezregel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "Trapez")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Trapezregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Tangententrapez-Regel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "TangentTrapezoidal")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Tangententrapezregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Mittelpunkt/Rechteckregel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_IntAccurate($IntFunction, $a, $b, $EPS, "Rectangle")
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\tn: %4d\n", "Mittelpunktregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), $k))

    [/autoit] [autoit][/autoit] [autoit]

    ; Die Monte-Carlo-Regel (für 1D nicht schön - für höhere Dimensionen hingegen sehr bedeutend)
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_MonteCarlo($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %5.2e\t\n", "Monte-Carlo", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))
    #EndRegion Vergleich der verschiedenen Algorithmen bezüglich Genauigkeit und Geschwindigkeit

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Berechnung des Bogenintegrals
    $f_Kurvenlaenge = _MathIntLineIntegral($IntFunction, $a, $b, $EPS)
    ConsoleWrite(StringFormat("\n------------------ Kurvenintegral --------------------\nKurvenlänge von %.2f bis %.2f: %.20f\n\n", $a, $b, $f_Kurvenlaenge))
    #EndRegion Berechnung des Bogenintegrals

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Funktionen zur Berechnung einer numerischen Integration
    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_IntAccurate
    ; Description ...: Berechnet das bestimmte Integral eindimensionalen Funktion mit
    ; einer festzulegenden Genauigkeit mit verschiedenen Algorithmen
    ; Syntax.........: _MathInt_IntAccurate(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $s_Method = "DoubleExponential")
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $EPS - zu erreichender Integrationsfehler
    ; $s_Method - Integrationsmethode (Werte: "Rectangle"|"DoubleExponential"|"Trapez"|"TangentTrapezoidal"|"Simpson"|"Gauss")
    ; Return values .: Integral in den Grenzen $a-$b, @extended = Anzahl benötigter Iterationen
    ; @error = 1: Maximale Iterationsanzahl erreicht
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_IntAccurate(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $s_Method = "DoubleExponential")
    Local $s, $s0 = 0, $dx0 = 10e50, $i = 4, $dx
    Do
    Switch $s_Method
    Case "Rectangle"
    $s = _MathInt_Rectangle($cb_F, $a, $b, $i)
    Case "DoubleExponential"
    $s = _MathInt_DoubleExponential($cb_F, $a, $b, $i)
    Case "Trapez"
    $s = _MathInt_Trapezoidal($cb_F, $a, $b, $i)
    Case "TangentTrapezoidal"
    $s = _MathInt_TangentTrapezoidal($cb_F, $a, $b, $i)
    Case "Simpson"
    $s = _MathInt_Simpson($cb_F, $a, $b, $i)
    Case "Gauss"
    $s = _MathInt_Gauss($cb_F, $a, $b, $i)
    Case Else
    Return SetError(1, 0, False)
    EndSwitch
    $dx = Abs($s - $s0)

    [/autoit] [autoit][/autoit] [autoit]

    If $dx = 0 And $i <> 1 Then ExitLoop
    If $i > 2 And $dx0 < $EPS Then ExitLoop
    $dx0 = $dx
    $s0 = $s
    $i *= 2
    If $i > 1048576 Then Return SetError(1, Log($i) / Log(2), $s)
    Until 0
    Return SetExtended(Log($i) / Log(2), $s)
    EndFunc ;==>_MathInt_IntAccurate

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Romberg
    ; Description ...: Berechnet das bestimmte Integral eindimensionalen Funktion mit
    ; einer festzulegenden relativen Genauigkeit
    ; Syntax.........: _MathInt_Romberg(Const $a, Const $b, Const $EPS = 0.0001)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $EPS - zu erreichender relativer Integrationsfehler
    ; Hinweis: != absoluter Fehler, rel. Fehler = Abs(1-(berechneter Integralwert / wahrer Integralwert)
    ; $kMax - Maximale Anzahl an Halbierungsintervallen
    ; Return values .: Integral in den Grenzen $a-$b, @extended = Anzahl benötigter Iterationen
    ; @error = 1: Maximale Iterationsanzahl erreicht
    ; Remarks .......: Romberg-Integrationsalgorithmus
    ; Related .......: __F()
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Romberg(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $kMax = 15)
    Local $a_R1[$kMax + 1], $a_R2[$kMax + 1]
    Local $h = $b - $a, $n = 1, $sumf, $f

    [/autoit] [autoit][/autoit] [autoit]

    $a_R1[0] = 0.5 * $h * ((IsFunc($cb_F) ? $cb_F($a) : __F($cb_F, StringFormat("%.20f", $a))) + (IsFunc($cb_F) ? $cb_F($b) : __F($cb_F, StringFormat("%.20f", $b)))) ; Erste Approximation

    [/autoit] [autoit][/autoit] [autoit]

    For $k = 1 To $kMax ; Schrittweise halbieren
    $sumf = 0
    For $i = 1 To $n
    $sumf += (IsFunc($cb_F) ? $cb_F($a + ($i - 0.5) * $h) : __F($cb_F, StringFormat("%.20f", $a + ($i - 0.5) * $h)))
    Next
    $a_R2[0] = 0.5 * ($a_R1[0] + $h * $sumf) ; Trapezoid-Formel
    $f = 1.0
    For $j = 1 To $k ; Quadratur-Ordnung erhöhen
    $f *= 4
    $a_R2[$j] = ($f * $a_R2[$j - 1] - $a_R1[$j - 1]) / ($f - 1) ; Neue Approximation
    Next
    If $k > 1 Then ; Check auf Konvergenz
    If (Abs($a_R2[$k] - $a_R1[$k - 1]) <= ($EPS * Abs($a_R2[$k]))) Then ExitLoop
    If (Abs($a_R2[$k]) <= $EPS) And (Abs($a_R2[$k]) <= Abs($a_R2[$k] - $a_R1[$k - 1])) Then ExitLoop
    EndIf
    $h *= 0.5 ; Halbiere Schrittweite
    $n *= 2
    For $j = 0 To $k
    $a_R1[$j] = $a_R2[$j]
    Next
    Next
    If $k >= $kMax Then Return SetError(1, $k, $a_R2[$k - 1])
    Return SetExtended($k, $a_R2[$k])
    EndFunc ;==>_MathInt_Romberg

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Rectangle
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Mittelpunkt/Rechteckregel
    ; Syntax.........: _MathInt_Rectangle($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Mittelpunktregel/Rechteckregel
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Rectangle($cb_F, Const $a, Const $b, Const $n, $h = Default)
    Local $f_sum = 0.0
    If $h = Default Then $h = ($b - $a) / $n

    [/autoit] [autoit][/autoit] [autoit]

    For $j = 1 To $n
    $f_sum += (IsFunc($cb_F) ? $cb_F($a + ($j - 0.5) * $h) : __F($cb_F, StringFormat("%.20f", $a + ($j - 0.5) * $h)))
    Next
    Return $f_sum * $h
    EndFunc ;==>_MathInt_Rectangle

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Trapezoidal
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Sehnentrapezformel
    ; Syntax.........: _MathInt_Trapezoidal($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Sehnentrapezformel
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Trapezoidal($cb_F, Const $a, Const $b, Const $n, $h = Default)
    Local $f_sum = 0.0
    If $h = Default Then $h = ($b - $a) / $n

    [/autoit] [autoit][/autoit] [autoit]

    For $j = 1 To $n - 1
    $f_sum += (IsFunc($cb_F) ? $cb_F($a + $j * $h) : __F($cb_F, StringFormat("%.20f", $a + $j * $h)))
    Next
    Return $h * ($f_sum + ((IsFunc($cb_F) ? $cb_F($a) : __F($cb_F, StringFormat("%.20f", $a))) + (IsFunc($cb_F) ? $cb_F($b) : __F($cb_F, StringFormat("%.20f", $b)))) / 2)
    EndFunc ;==>_MathInt_Trapezoidal

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_TangentTrapezoidal
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Tangententrapezformel
    ; Syntax.........: _MathInt_TangentTrapezoidal($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Tangententrapezformel
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_TangentTrapezoidal($cb_F, Const $a, Const $b, Const $n, $h = Default)
    Local $f_sum = 0.0
    If $h = Default Then $h = ($b - $a) / $n

    [/autoit] [autoit][/autoit] [autoit]

    For $j = 1 To $n - 1
    $f_sum += (IsFunc($cb_F) ? $cb_F($a - (0.5 * $h) + $j * $h) : __F($cb_F, StringFormat("%.20f", $a - (0.5 * $h) + $j * $h)))
    Next
    Return $f_sum * $h
    EndFunc ;==>_MathInt_TangentTrapezoidal

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Simpson
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Simpsonregel
    ; Syntax.........: _MathInt_Simpson($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Simpsonregel
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Simpson($cb_F, Const $a, Const $b, Const $n, $h = Default)
    If $h = Default Then $h = ($b - $a) / $n
    Local $tn = _MathInt_Trapezoidal($cb_F, $a, $b, $n, $h)
    Local $mn = _MathInt_Rectangle($cb_F, $a, $b, $n, $h)

    [/autoit] [autoit][/autoit] [autoit]

    Return 1 / 3.0 * ($tn + 2 * $mn)
    EndFunc ;==>_MathInt_Simpson

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Gauss
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Gaussregel
    ; Syntax.........: _MathInt_Gauss($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Gaußquadratur
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Gauss($cb_F, Const $a, Const $b, Const $n, $h = Default)
    If $h = Default Then $h = ($b - $a) / $n
    Local $xi
    Local Const $f1 = ((Sqrt(3) - 1) / (2 * Sqrt(3))) * $h, $f2 = ((Sqrt(3) + 1) / (2 * Sqrt(3))) * $h
    Local $f_sum = 0.0

    [/autoit] [autoit][/autoit] [autoit]

    For $j = 0 To $n - 1
    $x_a = $a + $j * $h

    [/autoit] [autoit][/autoit] [autoit]

    $x1 = $x_a + $f1
    $x2 = $x_a + $f2

    [/autoit] [autoit][/autoit] [autoit]

    $f_sum += 0.5 * $h * ((IsFunc($cb_F) ? $cb_F($x1) : __F($cb_F, StringFormat("%.20f", $x1))) + (IsFunc($cb_F) ? $cb_F($x1) : __F($cb_F, StringFormat("%.20f", $x2))))
    Next
    Return $f_sum
    EndFunc ;==>_MathInt_Gauss

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_DoubleExponential
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der doppelt-exponentiellen Methode
    ; Syntax.........: _MathInt_DoubleExponential($cb_F, Const $a, Const $b, Const $n)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; Return values .: Integral in den Grenzen $a-$b
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_DoubleExponential($cb_F, Const $a, Const $b, $n)
    Local Const $PI = ACos(-1)
    Local $f_sum = 0.0, $z, $exz, $hcos, $hsin, $s, $w, $x, $dxdz
    $n /= 2
    Local $h = 5.0 / $n

    [/autoit] [autoit][/autoit] [autoit]

    For $k = -$n To $n
    $z = $h * $k
    $exz = Exp($z)
    $hcos = $exz + 1.0 / $exz
    $hsin = $exz - 1.0 / $exz
    $s = Exp($PI * $hsin)
    $w = $s + 1.0 / $s
    $x = ($b * $s + $a / $s) / $w
    If ($x <> $a And $x <> $b) Then
    $dxdz = 2 * ($b - $a) * $PI * $hcos / ($w * $w)
    $f_sum += $h * (IsFunc($cb_F) ? $cb_F($x) : __F($cb_F, StringFormat("%.20f", $x))) * $dxdz
    EndIf
    Next
    Return $f_sum
    EndFunc ;==>_MathInt_DoubleExponential

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_MonteCarlo
    ; Description ...: Berechnet das bestimmte Integral einer eindimensionalen Funktion
    ; mit der Carlo
    ; Syntax.........: _MathInt_MonteCarlo($cb_F, Const $a, Const $b, Const $n, $h = Default)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $n - Anzahl der Teilintervalle
    ; $h - Manuelle Schrittweite ($n wird dann ignoriert)
    ; Return values .: Integral in den Grenzen $a-$b
    ; Remarks .......: Monte-Carlo-Regel - für 1D gibt es effizientere - aber für höhere Dimensionen sehr wichtig
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_MonteCarlo($cb_F, Const $a, Const $b, Const $n)
    Local $xi
    Local $f_sum = 0.0

    [/autoit] [autoit][/autoit] [autoit]

    For $j = 1 To $n
    $f_sum += (IsFunc($cb_F) ? $cb_F(Random($a, $b)) : __F($cb_F, Random($a, $b)))
    Next
    Return (($b - $a) * $f_sum) / $n
    EndFunc ;==>_MathInt_MonteCarlo

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathIntLineIntegral
    ; Description ...: Berechnet das Linienintegral einer eindimensionalen Funktion
    ; Syntax.........: _MathIntLineIntegral(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $kMax = 30)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $EPS - zu erreichender relativer Integrationsfehler
    ; Hinweis: != absoluter Fehler, rel. Fehler = Abs(1-(berechneter Integralwert / wahrer Integralwert)
    ; $kMax - Maximale Anzahl an Halbierungsintervallen
    ; Return values .: Integral in den Grenzen $a-$b, @extended = Anzahl benötigter Iterationen
    ; @error = 1: Maximale Iterationsanzahl erreicht
    ; Related .......: __FLI(), _MathInt_Romberg(), _Abl1()
    ; Remarks .......: s(f(x))_a^b = int_a^b(sqrt( 1+ f'(x)^2))
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathIntLineIntegral(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $kMax = 30)
    Global $cb_HelpFuncForLineIntegral = $cb_F
    Return _MathInt_Romberg(__FLI, $a, $b, $EPS, $kMax)
    EndFunc ;==>_MathIntLineIntegral

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region Hilfsfunktionen
    ; Wrapperfunktion für den Fall, dass die zu integrierende Funktion als String übergeben wird
    Func __F($s_Func, $x)
    $s_Func = StringReplace($s_Func, "exp", "§")
    $s_Func = StringReplace($s_Func, "x", $x)
    $s_Func = StringReplace($s_Func, "§", "exp")
    Return Execute($s_Func)
    EndFunc ;==>__F

    [/autoit] [autoit][/autoit] [autoit]

    ; help-function for _MathIntLineIntegral
    Func __FLI(Const $x)
    Return Sqrt(1 + _Abl1($cb_HelpFuncForLineIntegral, $x) ^ 2)
    EndFunc ;==>__FLI

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION#=================================================================================
    ; Name...........: _Abl1
    ; Description ...: Berechnet die 1. Ableitung einer Funktion F(x) an der Stelle x
    ; Methode: "zentraler Differenzenquotient"
    ; Syntax.........: _Abl1(Const $cb_F, Const $x, Const $FLT_EPSILON = 1E-15)
    ; Return values .: Wert der 1. Ableitung
    ; Parameters.....: $cb_F: Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $x: Wert der Funktionsvariable
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _Abl1(Const $cb_F, Const $x, Const $FLT_EPSILON = 1E-15)
    Local Const $h = $FLT_EPSILON ^ (1 / 3)
    If IsFunc($cb_F) Then
    Return ($cb_F($x + $h) - $cb_F($x - $h)) / (2 * $h)
    Else
    Return (__F($cb_F, StringFormat("%.20f", $x + $h)) - __F($cb_F, StringFormat("%.20f", $x - $h))) / (2 * $h)
    EndIf
    EndFunc ;==>_Abl1
    #EndRegion Hilfsfunktionen
    #EndRegion Funktionen zur Berechnung einer numerischen Integration

    [/autoit]
  • [Blockierte Grafik: http://gifwelt.info/wp-content/uploads/s-reaktionen-huldigung.gif]
    Sehr fein! Im Zweifelsfall kann man mehrere Funktionen verwenden, um sich genau die "passende" auszusuchen!