Mini UDF - 2-2 / 3-3 Gleichungsysteme lösen

  • Ich hatte mal die Idee eine Mini UDF für die Lösung von 2-2 bzw. 3-3 Gleichungsystemen. Ich hab mich dann an die Arbeit mit Autoit gemacht und festgestellt das es nichts wird. Also hab ichs fix in Excel gemacht und suche nun Leute die das mit mir in Autoit zu einer Mini UDF umwandeln.

    Die XLS´s sind im Anhang!

    Kontakt hier im Forum

  • Hi,
    hatte sowas schon vor einiger Zeit benutzt:
    Löst n Gleichungen mit n Unbekannten nach dem Gaußschen Eliminationsverfahren

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>

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

    ;linearer gleichungslöser nach Gaußschem Eliminationsverfahren,
    ;$n = 3
    ;Dim $a[$n][$n] = [[1, 1, 0],[1, 0, 1],[0, 1, 1]] ;matrix
    ;Dim $b[$n] = [28, 30, 32] ;lösungen

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

    ;~ $n = 4
    ;~ Dim $a[$n][$n] = [[1, 3, -2, 1],[-2, 1, -4, -5],[1, -3, 1, 0],[-3, 4, -6, 2]] ;matrix
    ;~ Dim $b[$n] = [-7, -6, 6, -21] ;lösungen
    ;~ $s = _solve_linear_quad($a, $b)
    ;~ _ArrayDisplay($s)

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

    Global $num_unknowns = Number(InputBox("Lösung Lineare Gleichungssysteme", "Anzahl Unbekannte?", 3))
    Dim $coeff[$num_unknowns][$num_unknowns] ;matrix
    Dim $values[$num_unknowns + 1][$num_unknowns + 2] ;
    Dim $b[$num_unknowns] ;lösungen
    GUICreate("Enter Equations:", (48 * $num_unknowns) + 121, (26 * $num_unknowns) + 77)
    For $n = 1 To $num_unknowns
    For $r = 1 To $num_unknowns
    $values[$n][$r] = GUICtrlCreateInput("", 48 * $r, 26 * $n, 25, 21)
    GUICtrlCreateLabel(StringMid("abcdefghijklmnopqrstuvwxyz", $r, 1), (48 * $r) + 26, (26 * $n) + 5, 10, 17)
    If $r < $num_unknowns Then
    GUICtrlCreateLabel("+", (48 * $r) + 37, (26 * $n) + 5, 10, 17)
    Else
    GUICtrlCreateLabel("=", (48 * $r) + 37, (26 * $n) + 5, 10, 17)
    EndIf
    Next
    $values[$n][$r] = GUICtrlCreateInput("", 48 * $r, 26 * $n, 25, 21)
    Next
    $solve_button = GUICtrlCreateButton("Lösen", (48 * $num_unknowns) + 38, (26 * $num_unknowns) + 36, 50, 25)
    GUISetState()

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

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    ExitLoop
    Case $solve_button
    For $n = 0 To $num_unknowns - 1
    For $r = 0 To $num_unknowns - 1
    $coeff[$n][$r] = Number(GUICtrlRead($values[$n + 1][$r + 1]))
    Next
    $b[$n] = Number(GUICtrlRead($values[$n + 1][$num_unknowns + 1]))
    Next
    ;~ _arraydisplay($b)
    ;~ _arraydisplay($coeff)

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

    GUISetState(@SW_HIDE)
    $sols = _solve_linear_quad($coeff, $b)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sols = ' & $sols & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

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

    $solutWin = GUICreate("Lösungen:", 280, (21 * UBound($sols)) + 42)
    For $n = 0 To UBound($sols) - 1
    GUICtrlCreateLabel(StringMid("abcdefghijklmnopqrstuvwxyz", $n + 1, 1) & " = " & Round($sols[$n], 3) & " (Max. 3 Nachkommastellen)", 30, 21 * ($n + 1), 200, 20)
    Next
    GUISetState(@SW_SHOW, $solutWin)
    EndSwitch
    WEnd

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

    Func _solve_linear_quad($a, $b) ;matrix,lösung Gaußsches Eliminationsverfahren, löst x gleichungen mit x unbekannten
    ;by Andy http://www.autoit.de
    Local $n, $t
    Dim $Y[UBound($b)] ;ergebnisse
    $n = UBound($a) - 1 ;anzahl der zeilen/spalten
    ;falls erforderlich, zeilen und spalten tauschen
    If $a[0][0] = 0 Then ;wenn erster koeffizient = 0, dann kann das system nicht starten => spalten tauschen ggf zeilen tauschen
    For $k = 0 To $n ;jede zeile
    For $j = 0 To $n ;alle spalten in dieser Zeile testen
    If $a[$k][$j] <> 0 Then
    For $m = 0 To $n ;treffer, die erste spalte mit der j. tauschen
    $t = $a[$m][$j] ;sichern
    $a[$m][$j] = $a[$m][0] ;mit erster spalte tauschen
    $a[$m][0] = $t
    Next
    For $j = 0 To $n ;zeilen tauschen
    $t = $a[0][$j] ;sichern
    $a[0][$j] = $a[$k][$j] ;mit erster spalte tauschen
    $a[$k][$j] = $t
    Next
    $t = $b[0] ;ergebnisse auch tauschen
    $b[0] = $b[$k]
    $b[$k] = $t
    ExitLoop 2
    EndIf
    Next
    Next
    EndIf

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

    If $a[0][0] = 0 Then Return SetError(1, 0, 1)

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

    ;endlich rechnen :)
    For $I = 0 To $n ;alle zeilen
    If $a[$I][$I] <> 0 Then
    ;erstes element auf 1 bringen indem man gesamte zeile durch erstes Element teilt
    For $k = $I To $n
    $t = $a[$k][$I] ;erstes element merken
    If $t <> 0 Then ;nur, wenn das erste element ungleich null ist...
    For $j = $I To $n
    $a[$k][$j] /= $t ;alle zeilenmitglieder durch erstes element teilen
    Next
    ;b durch i teilen
    $b[$k] /= $t ;ergebnis natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "oben " & $I)
    ;zeile i von allen weiteren zeilen subtrahieren, erstes element wird zu 0
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;wenn null, dann überspringen
    For $j = $I To $n
    $a[$k][$j] -= $a[$I][$j] ;die i.zeile von der aktuellen zeile subtrahieren
    Next
    $b[$k] -= $b[$I] ;ergebnisse natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "unten " & $I)
    Else ;null in aktueller spalte
    ;zeilen tauschen
    ; msgbox(0,$i,"null gefunden")
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;zeile tauschen
    For $j = $I To $n ;zeilen tauschen
    $t = $a[$I][$j] ;sichern
    $a[$I][$j] = $a[$k][$j] ;mit erster spalte tauschen
    $a[$k][$j] = $t
    Next
    $t = $b[$I] ;ergebnisse auch tauschen
    $b[$I] = $b[$k]
    $b[$k] = $t
    EndIf
    ;erstes element auf 1 bringen indem man gesamte zeile durch erstes Element teilt
    For $k = $I To $n
    $t = $a[$k][$I] ;erstes element merken
    If $t <> 0 Then ;nur, wenn das erste element ungleich null ist...
    For $j = $I To $n
    $a[$k][$j] /= $t ;alle zeilenmitglieder durch erstes element teilen
    Next
    ;b durch i teilen
    $b[$k] /= $t ;ergebnis natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "oben1 " & $I)
    ;zeile i von allen weiteren zeilen subtrahieren, erstes element wird zu 0
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;wenn null, dann überspringen
    For $j = $I To $n
    $a[$k][$j] -= $a[$I][$j] ;die i.zeile von der aktuellen zeile subtrahieren
    Next
    $b[$k] -= $b[$I] ;ergebnisse natürlich auch
    EndIf
    Next
    ;_ArrayDisplay($a, "unten1 " & $I)

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

    Next
    EndIf
    Next

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

    ;alle parameter bestimmen durch rückwärtseinsetzen

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

    $Y[$n] = $b[$n] ;letzter ist bereits bekannt
    For $I = $n - 1 To 0 Step -1
    For $j = $n To $I + 1 Step -1
    $b[$I] -= $a[$I][$j] * $Y[$j]
    Next
    $Y[$I] = $b[$I]
    Next
    Return $Y
    EndFunc ;==>_solve_linear_quad
    Exit

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