Gleichungen lösen
-
- [ offen ]
-
Molaynox -
12. Februar 2011 um 12:25 -
Geschlossen -
Erledigt
-
-
Mahlzeit,
also erstmal vorweg: ich berufe mich nur auf Erfahrungswerte / Vermutungen...Ich schätze, wenn du mithilfe von AutoIt die Lösung berechnen lassen willst, dann musst
du dir einen Parser schreiben, der dann die Formel(n) in einzelne logische Bestandteile packt.
Beispiel: Gleichung 1 wird genau dann 0, wenn x das additive Inverse von 6, also -6 annimmt.
Zu Gleichung 2 fällt uns sofort ein, dass ein Produkt genau dann 0 wird, wenn mindestens einer
der Faktoren 0 ist. Somit gilt es (wie oben) die einzelnen Faktoren 0 zu bekommen.
-4 * x = 0 => x = 0
5 + 2x = 0 <=> 2x = -5 => x = -5/2
3x-9=0 <=> 3x = 9 => x = 3
das ganze in einen logischen Kontext zu bringen stelle ich mir jedoch schwierig vor.
Ganz schlecht ist es mit ausprobieren (= Bruteforce), da z.B. -5/2 nur schwer erfasst wird.
PS: Vielleicht findest du ja schon eine Lösung im Forum, die dir hilft
Wenn du das [Projekt] "größer" aufziehst, dann wäre ich sehr gespannt, was dabei rauskommt.
Viel Glück -
Naja, GANZ billig kann man die Gleichung so lösen:
[autoit]
[/autoit]
$gleichung="x+6 == 0"
For $i=-1000 To 1000 Step 1
If(Execute(StringReplace($gleichung,"x",$i/100))) Then MsgBox(64,"Lösung","x ist " & $i/100)
ConsoleWrite(Execute(StringReplace($gleichung,"x",$i/100)) & @CRLF)
ConsoleWrite(StringReplace($gleichung,"x",$i/100) & @CRLF)
Next -
Ich habe nun das hier gefunden:
Spoiler anzeigen
Code
Alles anzeigenSub gauss(n%, A() As Double, x() As Double) Dim i%, j%, k%, jmax%, kmax%, merk() As Integer Dim s As Double, max As Double, skal() As Double ReDim merk(n), skal(n) 'Reihenfolge sichern For i = 1 To n merk(i) = i Next 'Normalisierung For i = 1 To n s = 0 For j = 1 To n s = s + Abs(A(i, j)) Next skal(i) = 1 / s Next 'Vorwärtselimination For k = 1 To n - 1 max = skal(k) * Abs(A(k, k)) kmax = k 'Spalte mit max jmax = k 'Zeile mit max For j = k To n 'Pivotzelle suchen For i = k To n If skal(j) * Abs(A(j, i)) > max Then jmax = j kmax = i max = skal(j) * Abs(A(j, i)) End If Next Next If jmax <> k Then 'Zeilentausch, wenn nötig For j = k To n + 1 s = A(k, j) A(k, j) = A(jmax, j) A(jmax, j) = s Next s = skal(k) skal(k) = skal(jmax) skal(jmax) = s End If If kmax <> k Then 'Spaltentausch, wenn nötig For i = 1 To n s = A(i, k) A(i, k) = A(i, kmax) A(i, kmax) = s Next j = merk(k) merk(k) = merk(kmax) merk(kmax) = j End If 'eigentliche Elimination For i = k + 1 To n s = A(i, k) / A(k, k) A(i, k) = 0# For j = k + 1 To n + 1 A(i, j) = A(i, j) - s * A(k, j) Next Next Next 'Auflösung rückwärts x(merk(n)) = A(n, n + 1) / A(n, n) For i = n - 1 To 1 Step -1 s = A(i, n + 1) For j = i + 1 To n s = s - A(i, j) * x(merk(j)) Next x(merk(i)) = s / A(i, i) Next End Sub
Bringt mir das irgendwas? Wie kann ich das genau verwenden? -
Naja, der Code ist auf jeden Fall nicht in AutoIt, also musst du ihn dir übersetzen (lassen) wenn du ihn nutzen willst.
-
Aber der ist Autoit sehr ähnlich (vllt. Visual Basic?)
Das übersetzen schaffe ich vielleicht sogar alleine. -
Numerisch lässt es sich ziemlich einfach in AutoIt lösen:
Spoiler anzeigen
[autoit]Global Const $FLT_EPSILON = _GET_FLT_EPSILON()
[/autoit] [autoit][/autoit] [autoit]; Definition der Funktionen
[/autoit] [autoit][/autoit] [autoit]
Global $sF1 = "-4*x*(5+2*x)*(3*x-9)"
Global $sF2 = "0"; Definition des Suchbereiches
[/autoit] [autoit][/autoit] [autoit]
Global $iStart = -1000
Global $iEnd = 1000
Global $iStep = 1.1; Größer/Kleiner Vergleichskriterium
[/autoit] [autoit][/autoit] [autoit]
Global $bSw = _Fx($sF1, $iStart) > _Fx($sF2, $iStart)For $x = $iStart To $iEnd Step $iStep ; Gehe den Bereich grob ab
[/autoit] [autoit][/autoit] [autoit]
If $bSw <> (_Fx($sF1, $x) > _Fx($sF2, $x)) Then ; Wenn Wechsel der Größer/Kleiner Beziehung dann muss Schnittpunkt dazwischen liegen
$bSw = Not $bSw
$dX_Schnitt = Schnittsuche($sF1, $sF2, $x - $iStep, $x) ; Starte die feine Schnittpunktsuche im Intervall
$dY_Schnitt = (_Fx($sF1, $dX_Schnitt) + _Fx($sF2, $dX_Schnitt)) / 2 ;Y-Wert als Mittelwert beider Funktionswerte bestimmen
MsgBox(0, "Schnittpunkt gefunden", "x = " & Round($dX_Schnitt,15) & @CRLF & "y = " & Round($dY_Schnitt,14))
EndIf
NextFunc _Fx(Const $sF, Const $dW)
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Return Number(Execute(StringReplace($sF, "x", "(" & $dW & ")")))
EndFunc ;==>_Fx; Bestimmt die Schnittpunkte 2er Funktionen in einem Intervall iterativ mit dem Regula Falsi Algorithmus
[/autoit] [autoit][/autoit] [autoit]
; Hinweis: Sollte noch ungültige Ergebnisse liefern wenn einer der Grenzen = dem Schnittpunkt
Func Schnittsuche(Const $sF1, Const $sF2, $dA, $dB, $iMaxIt = 100)
;by AspirinJunkie
Local $xA = $dA, $xB = $dB
Local $Ya, $Yb, $x, $Yx
Local $xOld = $dBFor $n = 1 To $iMaxIt
[/autoit] [autoit][/autoit] [autoit]
$Ya = _Fx($sF1, $xA) - _Fx($sF2, $xA) ;Differenz der Funktionen da Regula Falsi nach Nullstellen sucht
$Yb = _Fx($sF1, $xB) - _Fx($sF2, $xB)
$x = $xA - ($Ya * ($xB - $xA)) / ($Yb - $Ya)
$Yx = _Fx($sF1, $x) - _Fx($sF2, $x)If Abs($x - $xOld) < (4 * $FLT_EPSILON) Or Abs($Yx) < (5 * $FLT_EPSILON) Then ; Wenn Differenz der Durchgänge unter einer gewissen Genauigkeit liegt abbrechen
[/autoit] [autoit][/autoit] [autoit]
Return $x
Else ;Festlegung der neuen grenzen für den neuen Durchlauf
$xOld = $x
If $Ya > $Yx Then
$xA = $x
Else
$xB = $x
EndIf
EndIfNext
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Return SetError(1, $iMaxIt, $x)
EndFunc ;==>Schnittsuche; #FUNCTION#=================================================================================
[/autoit]
; Name...........: _GET_FLT_EPSILON
; Description ...: Berechnet den binären Rundungsfehler und damit die Rechengenauigkeit
; Syntax.........: _GET_FLT_EPSILON
; Return values .: Epsilon
; Author ........: AspirinJunkie
;============================================================================================
Func _GET_FLT_EPSILON()
Local $x = 1
Do
$x /= 2
Until 1 + $x <= 1
Return $x
EndFunc ;==>_GET_FLT_EPSILON -
Hi,
Newton mal sehr simpel umgesetzt:
findet die nächste Nullstelle vom StartpunktSpoiler anzeigen
[autoit];funktion eintragen
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Func y($x)
Return -4*$x*(5+2*$x)*(3*$x-9)
EndFunc ;==>y$x1 = 11 ;irgendein startpunkt
[/autoit] [autoit][/autoit] [autoit]Do
[/autoit] [autoit][/autoit] [autoit]
$x0 = $x1
$x1 = tangentenschnitt($x0);ergibt nächsten punkt auf der x-achse
; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $x1 = ' & $x1 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
Until Abs($x1 - $x0) < 1E-11ConsoleWrite("Lösung y (" & $x1 & ") = "&y($x1)&@crlf)
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]Func tangentenschnitt($x, $delta = 1E-13);tangente ermitteln und schnittpunkt mit der x-achse
[/autoit] [autoit][/autoit] [autoit][/autoit]
$y1 = y($x)
$y2 = y($x + $delta)
$m = ($y2 - $y1) / $delta
$b = $y1 - $m * $x
Return -$b / $m
EndFunc ;==>tangentenschnitt-1#INF muss noch abgefangen werden, ggf auch eine startposition gefunden anhand der Funktion usw, aber schonmal ein Anfang für die Nullstellensuche