• Hi,

    ich hab mir letztens mal das Thema Integralrechnung angeschaut und dachte mir das wäre doch in AutoIt machbar.
    Falls jemand nicht weiß, was ein Integral ist hier eine kurze Erklärung + Rechnung:

    Integralrechnung - Erklärung und Beispielsrechnung

    Ein Integral einer Funktion ist die Fläche die sich über oder unterhalb der X-Achse im Koordinatensystem befindet.
    Die Fläche unterhalb der Funktion und über der X-Achse ist positiv und die Fläche über der Funktion und unter der X-Achse ist negativ.
    Das wird verrechnet (positive und negative Fläche) und dann hat man das Integral einer Funktion.

    Da ich am Anfang nicht wusste wie man das ausrechnen könnte,
    da ja fest jede Funktion eine andere Form hat und man es nicht genau ermitteln kann hab ich es so gelöst:

    Ich habe einen Wert X. Ich verrechne den Wert, der ist bsp.-weise 2. In f(x) = x wäre das f(2) = 2.
    Dann addiere ich zu X einen kleinen Wert, der ist konstant 0.001. Daraus folgt: f(2 + 0.001) = 2.001
    Anschließend errechne ich die Fläche des Trapezes mittels einfacher Mathematik.

    Die lange Strecke (je nach dem welcher Wert bei f(x) höher ist) - die kurze Strecke.
    Da es ja ein Trapez ist, kann man das Trapez durch folgende 2 Formen definieren:

    Quadrat und Dreieck.

    Das Quadrat wäre die kleine Strecke * 2.
    Das Dreieck wäre (die lange Strecke - die kurze) * 0.001 / 2.
    Beides zusammenaddiert ergibt es das Integral der Funktion an der Stelle X und X + 0.001.

    So rechnet man in kleinen Schritten immer weiter bis man an dem Ende - 0.001 angekommen ist.

    Das hört sich für einige Leute an als ob jemand an der Matratze kratzen würde aber hoffentlich war es ohne zeigen verständlich.
    Falls Unklarheiten sind hier ist eine Beispielrechnung:

    Wir wollen das Integral der Funktion f(x) = x an der Stelle 1 bis 3.
    Wir benutzen hier nicht mehr 0.001 als Schritt sondern 2, weil es ein Trapez ist, und wir nicht unnötig kleine Schritte machen müssen.

    Wenn wir in die Funktion f(x) = x für x 1 einsetzen kommt folgendes raus f(1) = 1.
    Wenn wir für die Funktion f(x) = x für x 1 + 2 einsetzen kommt folgendes raus f(1+2) = 3.

    Berechnung des Quadrats:
    Da 1 der kleinere Wert von 1 und 3 ist rechnen wir:
    1 * 2 = 2.

    Die Fläche des Quadrats ist 2 LE² (Längeneinheiten).

    Berechnung des Dreiecks:
    Da 3 der höhere Wert von 1 und 3 ist rechnen wir:
    (3 - 1) * 2 / 2 = 2.

    Die Fläche des Dreiecks ist 2 LE².

    Somit wäre das Integral der Funktion f(x) = x an der Stelle 1 bis 3:
    2 LE² + 2 LE² = 4 LE².


    Das wars auch eigentlich schon, die Rechnung könnt ihr euch im Script anschauen, es gibt noch Besonderheiten bei negativen Werten deshalb ist das If da.

    Wichtig für beide Versionen!!!
    Ihr müsst die Werte unterschiedlich bei unterschiedlichen Funktionen runden da es nur Näherungswerte sind.
    So wäre bei f(x) = x an der Stelle 1 bis 3 3.99970000500089 bei einem Step von 0.0001 4!

    Wichtig für die Version ohne Solver!!!

    Spoiler anzeigen
    [autoit]


    ;...
    $fX = $fValue
    $fX_ = $fValue + $fStep
    ;...

    [/autoit]


    Wenn ihr andere Funktionen ausprobieren möchtet setzt $fValue + $fStep in Klammern!!!
    Die Funktion ist hier f(x) = x. Wenn ihr z.B. f(x) = x² oder x³ möchtet dann macht ihr bsp.-weise folgendes:
    $fX = $fValue^3
    $fX_ = ($fValue + $fStep)^3


    Script hier oder im Anhang

    Integralrechner ohne Funktionsgleichung
    [autoit]


    Global Const $fBegin = 1, _
    $fEnd = 3, _
    $fStep = 0.0001

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

    Global $fX, $fX_, $fArea

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

    For $fValue = $fBegin To $fEnd - $fStep Step $fStep
    $fX = $fValue
    $fX_ = $fValue + $fStep

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

    If ($fX_ < $fX and $fX_ > 0) or ($fX_ > $fX and $fX_ < 0) Then
    $fArea += $fStep * $fX_ + ($fX - $fX_) * $fStep / 2
    Else
    $fArea += $fStep * $fX + ($fX_ - $fX) * $fStep / 2
    EndIf
    Next

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

    MsgBox(64, "Integral", "Die Fläche des Integrals der Funktion f(x) = x an der Stelle: " & $fBegin & " bis " & $fEnd & " beträgt: " & $fArea)

    [/autoit]
    Integralrechner mit Funktionsgleichung
    [autoit]

    Global Const $fBegin = 1, _
    $fEnd = 3, _
    $fStep = 0.0001, _
    $sFunction = "x"

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

    Global $fX, $fX_, $fArea

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

    For $fValue = $fBegin To $fEnd - $fStep Step $fStep
    $fX = Execute(StringReplace($sFunction, "x", $fValue))
    $fX_ = Execute(StringReplace($sFunction, "x", $fValue + $fStep))

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

    If ($fX_ < $fX and $fX_ > 0) or ($fX_ > $fX and $fX_ < 0) Then
    $fArea += $fStep * $fX_ + ($fX - $fX_) * $fStep / 2
    Else
    $fArea += $fStep * $fX + ($fX_ - $fX) * $fStep / 2
    EndIf
    Next

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

    MsgBox(64, "Integral", "Die Fläche des Integrals der Funktion f(x) = " & $sFunction & " an der Stelle: " & $fBegin & " bis " & $fEnd & " beträgt: " & $fArea)

    [/autoit]
    Integralrechner mit Funktionsgleichung als AutoIt-Funktion
    [autoit]


    MsgBox(64, "Integral", "Die Fläche des Integrals der Funktion f(x) = " & "x^2" & " an der Stelle: " & "1" & " bis " & "3" & " beträgt: " & _Integral("x^2", 1, 3))

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

    Func _Integral($sFunction, $fBegin, $fEnd, $fStep = 0.0001)
    Local $fX, $fX_, $fArea

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

    For $fValue = $fBegin To $fEnd - $fStep Step $fStep
    $fX = Execute(StringReplace($sFunction, "x", $fValue))
    $fX_ = Execute(StringReplace($sFunction, "x", $fValue + $fStep))

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

    If ($fX_ < $fX and $fX_ > 0) or ($fX_ > $fX and $fX_ < 0) Then
    $fArea += $fStep * $fX_ + ($fX - $fX_) * $fStep / 2
    Else
    $fArea += $fStep * $fX + ($fX_ - $fX) * $fStep / 2
    EndIf
    Next

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

    Return $fArea
    EndFunc

    [/autoit]


    Da die Performanz in AutoIt in einigen Bereichen oder generell zu wünschen lässt, kann es bei kleineren Schritten länger dauern.

    Wenn jemand eine andere Methode kennt das Integral rauszufinden oder einen anderen Lösungsweg weiß bitte her damit!
    Ich weiß das man die ganze Funktion integrieren kann aber allein um die Funktion "12*(x-2)+4" zu trennen bzw. den String zu solven dauert das ein bisschen.
    Mit Execute und StringReplace geht das ganze viel besser von der Hand.

    Hoffentlich gefällts euch, Kritik und Lob erwünscht!

  • Hoffentlich gefällts euch, Kritik und Lob erwünscht!

    Ja gefällt mir sehr.
    Das Verfahren wird wirklich so ähnlich wie du es gelöst hast bei der numerischen Integralberechnung verwendet.
    Die Funktion wird in einem Intervall durch eine einfache Fläche (Rechteck, Trapez etc.) approximiert und damit ein Näherungswert für die Fläche berechnet.
    Wenn man das große Intervall in viele kleine unterteilt und das in jedem Intervall macht kann man die Genauigkeit beliebig steigern.

    Ich weiß das man die ganze Funktion integrieren kann aber allein um die Funktion "12*(x-2)+4" zu trennen bzw. den String zu solven dauert das ein bisschen.


    Du kannst ja stattdessen eine Funktion mit einem Parameter $x definieren und darin einfach AutoIt die Berechnung machen lassen.
    So kannst du ganz flexibel alle möglichen Funktionen implementieren. (Siehe mein folgendes Beispiel).

    Wenn jemand eine andere Methode kennst das Integral rauszufinden oder einen anderen Lösungsweg weiß bitte her damit!

    Das Prinzip bleibt immer das selbe. Die Funktion durch einfache Flächen ersetzen und aufsummieren.
    Die Verfahren unterscheiden sich dann lediglich darin welche Form genommen wird.
    Ich habe mal die Mittelpunktregel (Rechteck), Sehnentrapezregel, Tangententrapezregel, Simpsonregel und die Gaußquadratur implementiert.
    Bei diesen muss man explizit angeben in wieviel Teilintervalle der Bereich zerlegt wird womit man die Genauigkeit beeinflussen kann.
    Ein Sonderfall ist die Monte-Carlo Integration - hierbei werden zufällig Werte im Intervall berechnet und der Mittelwert berechnet (sieht ziemlich ineffizient aus - ist aber in höherdimensionalen Gleichungen unerlässlich).
    Zusätzlich gibt es noch die Funktion _MathInt_Calc mit welcher man eine zu erreichende Genauigkeit vorgeben kann.

    Diese Funktionen dienen vor allem dazu die verschiedenen Ansätze zu vergleichen.
    Für den produktiven Einsatz habe ich dann noch die Romberg-Integration implementiert, welche sowohl die Möglichkeit einer zu erreichende Genauigkeit besitzt und zusätzlich noch verdammt fix ist.
    Wenn man also in AutoIt integrieren muss - diese Funktion nehmen.
    Ebenfalls enthalten ist eine Funktion zur Berechnung des Kurvenintegrals.

    Integralberechnung
    [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-10

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

    Global $n = 10 ; Anzahl an Wiederholungen für die Zeitmessung
    Global $d_Steps = 256 ; Anzahl der Teilintervalle für die Mittelpunkt/Trapez/Gauß/Simpson/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"))
    ; Die Mittelpunkt/Rechteckregel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_Rectangle($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\t\n", "Mittelpunktregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

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

    ; Die Tangententrapez-Regel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_TangentTrapezoidal($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\t\n", "Tangententrapezregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

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

    ; Die Trapezregel:
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_Trapezoidal($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\t\n", "Trapezregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

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

    ; Die Simpson-Regel
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_Simpson($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\t\n", "Simpsonregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

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

    ; Die Gauss-Regel
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_Gauss($IntFunction, $a, $b, $d_Steps)
    Next
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\t\n", "Gaußregel", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

    [/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: %18.16f\t\n", "Monte-Carlo", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int)))

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

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

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

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

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

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

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

    ; Die Funktion _MathInt_CalcAdaptive
    $iT = TimerInit()
    For $i = 1 To $n
    $Int = _MathInt_CalcAdaptive($IntFunction, $a, $b, $EPS)
    Next
    $k = @extended
    ConsoleWrite(StringFormat("%30s: %5.2f ms\tWert: %20.16f\tEPS: %18.16f\tn: %4d\n", "_MathInt_CalcAdaptive", TimerDiff($iT) / $n, $Int, Abs($f_RealValue - $Int), Log($k) / Log(2)))
    #EndRegion Vergleich der verschiedenen Algorithmen bezüglich Genauigkeit und Geschwindigkeit

    [/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]

    #Region Funktionen zur Berechnung einer numerischen Integration
    ; #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
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Romberg(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $kMax = 30)
    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 = 1e0
    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]

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_Calc
    ; Description ...: Berechnet das bestimmte Integral eindimensionalen Funktion mit
    ; einer festzulegenden Genauigkeit
    ; Syntax.........: _MathInt_Calc(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 erreichende Genauigkeit
    ; $nMax - Maximale Iterationsanzahl
    ; Return values .: Integral in den Grenzen $a-$b, @extended = Anzahl benötigter Iterationen
    ; @error = 1: Maximale Iterationsanzahl erreicht
    ; Remarks .......: Genauigkeitsabschätzung über Vergleich von Gauß mit Simpson-Ergebnissen
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_Calc(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, $nMax = 8192)
    Local $n = 1, $h, $rf, $g, $S

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

    Do
    $n *= 2
    $h = ($b - $a) / $n
    $g = _MathInt_Gauss($cb_F, $a, $b, $n, $h)
    $S = _MathInt_Simpson($cb_F, $a, $b, $n, $h)
    $rf = Abs($S - $g) / Abs($g)
    If $n >= $nMax Then Return SetError(1, $n, ($g + $S) / 2)
    Until $rf < $EPS
    Return SetError($n >= $nMax, $n, ($g + $S) / 2)
    EndFunc ;==>_MathInt_Calc

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

    ; #FUNCTION#=================================================================================
    ; Name...........: _MathInt_CalcAdaptive
    ; Description ...: Berechnet das bestimmte Integral eindimensionalen Funktion mit
    ; einer festzulegenden Genauigkeit
    ; Wie Funktion "_MathInt_Calc" aber mit adaptiver Schrittweitenanpassung zur
    ; Verringerung der notwendigen Iterationen
    ; Syntax.........: _MathInt_CalcAdaptive(Const $a, Const $b, Const $EPS = 0.0001, Const $nMax = 8192, Const $maxRec = 64)
    ; Parameters ....: $cb_F - Funktionsvariable oder Funktionsstring einer 1D-Funktion f(x)
    ; $a - Untere Integrationsgrenze
    ; $b - obere Integrationsgrenze
    ; $EPS - zu erreichende Genauigkeit
    ; $nMax - Maximale Iterationsanzahl
    ; $maxRec - Maximale Rekursionstiefe
    ; Return values .: Integral in den Grenzen $a-$b, @extended = Anzahl benötigter Iterationen
    ; @error = 1 : Maximale Iterationsanzahl erreicht
    ; @error = 2 : Maximale Rekursionstiefe erreicht
    ; Author ........: AspirinJunkie
    ;============================================================================================
    Func _MathInt_CalcAdaptive(Const $cb_F, Const $a, Const $b, Const $EPS = 0.0001, Const $nMax = 8192, Const $maxRec = 64)
    Local $c = ($a + $b) / 2
    Local $h = $b - $a
    Local $fa = (IsFunc($cb_F) ? $cb_F($a) : __F($cb_F, StringFormat("%.20f", $a))), $fb = (IsFunc($cb_F) ? $cb_F($b) : __F($cb_F, StringFormat("%.20f", $b))), $fc = (IsFunc($cb_F) ? $cb_F($c) : __F($cb_F, StringFormat("%.20f", $c)))

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

    Local $Int = ($h / 6) * ($fa + 4 * $fc + $fb);
    Local $n = 0
    Local $S = __Simp($cb_F, $a, $b, $EPS, $Int, $fa, $fb, $fc, 0, $maxRec, $nMax, $n)
    Return SetError(@error, $n, $S)
    EndFunc ;==>_MathInt_CalcAdaptive

    [/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]

    ; #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]

    ; #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]

    ; #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]

    ; #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

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

    ; Hilfsfunktion für CalcIntegralAdaptiv
    Func __Simp(Const $cb_F, Const $a, Const $b, Const $EPS, Const $S, Const $fa, Const $fb, Const $fc, Const $curRec, Const $maxRec, Const $nMax, ByRef $n)
    $n += 1
    Local Const $c = ($a + $b) / 2, $d = ($a + $c) / 2, $e = ($c + $b) / 2
    Local Const $h = $b - $a

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

    Local Const $fd = (IsFunc($cb_F) ? $cb_F($d) : __F($cb_F, StringFormat("%.20f", $d))), $fe = (IsFunc($cb_F) ? $cb_F($e) : __F($cb_F, StringFormat("%.20f", $e)))

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

    Local $f_left = ($h / 12) * ($fa + 4 * $fd + $fc)
    Local $f_right = ($h / 12) * ($fc + 4 * $fe + $fb)
    Local $Int = $f_left + $f_right

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

    If $n >= $nMax Then Return SetError(1, 0, $Int)

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

    If $curRec >= $maxRec Then Return SetError(2, 0, $Int + ($Int - $S) / 15)
    If Abs($Int - $S) <= 15 * $EPS Then Return $Int + ($Int - $S) / 15

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

    Local $EPS2 = $EPS / 2

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

    Local $Int_L = __Simp($cb_F, $a, $c, $EPS2, $f_left, $fa, $fc, $fd, $curRec + 1, $maxRec, $nMax, $n)
    If @error Then Return SetError(@error, 0, $Int_L + __Simp($cb_F, $c, $b, $EPS2, $f_right, $fc, $fb, $fe, $curRec + 1, $maxRec, $nMax, $n))
    Local $Int_R = __Simp($cb_F, $c, $b, $EPS2, $f_right, $fc, $fb, $fe, $curRec + 1, $maxRec, $nMax, $n)
    Return SetError(@error, 0, $Int_L + $Int_R)
    EndFunc ;==>__Simp
    #EndRegion Hilfsfunktionen

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

    #EndRegion Funktionen zur Berechnung einer numerischen Integration

    [/autoit]

    11 Mal editiert, zuletzt von AspirinJunkie (17. September 2014 um 10:56)

  • Freut mich das es jemandem gefällt :)

    Zu der Sache mit der ganzen Funktion zu integrieren.
    Ich weiß nicht wie man einen String solven lassen kann.
    Wenn man in AutoIt einen String hat z.B.

    [autoit]


    $sFunction = "12*(x-2)+4"

    [/autoit]


    Dann kann man den String ja nicht solven lassen, es gibt keine Funktion dafür, deshalb muss man das leider so machen.
    Man braucht diese Funktion wenn man das in eine GUI einbauen möchte die für die Gleichung eine statt viele InputControls hat.

    Wenn man eine Solve-Funktion hat dann kann man ich die ganze Funktion integrieren und dann die Werte von 1-3 auslesen.
    Das gleiche ist bei Punktsteigung und Ableitung von Funktionen so.

  • Schau dir mal in meinem Beispiel an wie ich das mit der Funktion gemeint hatte.
    Wenn du wirklich die Funktion als String haben willst dann ersetze im String per StringReplace "x" mit dem jeweils aktuellen Wert von x.
    Den resultierenden String führst du dann einfach per Execute() aus und hast das Ergebnis.

    Ich hatte das >>hier<< schonmal genauso umgesetzt.

  • Ausrechnen kannst du per

    [autoit]


    Execute($vArg)

    [/autoit]

    Könnte vereinfacht so aussehen:

    Mini-Solver für Funktionsgleichungen
    [autoit]


    $sFunction = "12*(x-2)+4"

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

    For $iX = -10 To 10 Step 0.1 ;200 Werte...
    $iY = Execute(StringReplace($sFunction, "x", $iX))
    ConsoleWrite("X: " & $iX & @TAB & "Y: " & $iY & @CRLF)
    Next

    [/autoit]


    Im Browser getippt, also keine Garantie.

    lg

  • Wenn man eine Solve-Funktion hat dann kann man ich die ganze Funktion integrieren und dann die Werte von 1-3 auslesen.
    Das gleiche ist mein Punktsteigung und Ableitung von Funktionen so.

    Vielleicht kannst du ja folgendes gebrauchen:
    Ich hatte vor einiger Zeit mal ein paar Funktionen zur Kurvendiskussion geschrieben welche so mit den Funktionen umgehen wie du es machen willst:

    2 Mal editiert, zuletzt von AspirinJunkie (30. Juli 2015 um 14:03)