Determinantenberechnung einer Matrix

  • Hi,
    war nicht ganz so trivial, wie ich gedacht hatte: Meine Determinantenberechnung von FreeBasic nach AutoIt zu portieren..
    Also, eine Matrix ist eine Zahlenanordnung aus Zeilen und Spalten, AutoIt-Benutzern auch als Array[] bekannt, doch es gibt Unterschiede ;)
    Die Division durch eine Matrix wird als Multiplikation mit der Inversen ausgeführt, doch das nur am Rande.
    Aber wie bei jeder Division gibt es ein Problem, wenn der Divisor Null ist. Bei quadratischen Matrizen, wie sie z.B. in der Ausgleichungsrechnung vorkommen, läßt sich über die Berechnung der Determinanten(quasi der Wert) einer Matrix schon vor der Operation ermitteln, ob selbige überhaupt durchführbar ist. Gelingt das bei Zweier- oder Dreier-Matrizen fast noch per Kopfrechnung, so ist aber bereits bei einer Vierer-Matrix Schluß.
    Die Determinantenberechnung gestaltet sich sehr umständlich, da geschieht es leicht, dass sich Vorzeichenfehler einschleichen etc. pp.
    Als es das Computer-Magazin mc noch gab, habe ich dort irgendwann(~1985) mal ein Pascal-Programm gefunden, das diese Berechnung übernimmt.
    Erst habe ich es nach FreeBasic portiert und dann nach AutoIt, es funktioniert immer noch^^
    Wer mit dem Begriff Determinantenberechnung etwas anfangen kann, erhält hier ein Grundgerüst, mit dem soetwas auch mit AutoIt erledigt werden kann.
    Wer nix mit dieser Sache zu tun hat, der braucht das Programm auch nicht :rofl:
    Im GUI ist eine ganze Menge möglich, einfach mal anschauen, denn es kann nichts passieren(schließlich liefere ich den Quellcode ja mit)..
    Für den Fall, das jemand grad keine Matrix zur Hand hat, deren Determinante garantiert 0 ist, biddeschööön: 8)

    Code
    1 2 3
    4 5 6
    7 8 9

    Es gibt zwei eingebaute Matrizen, eine über das GUI zu finden, die andere, wenn in der Dimensionsauswahl der Eintrag max ausgewählt wird.
    Hier habe ich bei der einen den von einer Tabellenkalkulation ermittelten Wert eingetragen, im anderen Fall ist das Ergebnis 3, daran ist nicht zu rütteln. Sicherlich ließe sich noch vieles am GUI rumfeilen und besser/'schöner' machen, aber so ist es auf alle Fälle ausreichend, denn es ging
    ja nur darum, den Algorithmus etwas zu verpacken. Genug geredet, hier isses:

    Spoiler anzeigen
    [autoit]

    #include <ButtonConstants.au3>
    #include <ComboConstants.au3>
    #include <EditConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    ;+------------------------------------------------------------------------------------------+
    ;| Header: Bestimmen der Übergabeparameter |
    ;| AnzeigeCheck:|Il1 sind Alt-0124,Großes i,Kleines L, Eins „”᎙šñ¸=äöüßÄÖܱ© |
    Const $Author='Determinante.au3 ©2011 by ytwinky, MD'; |
    ;| (Tastenkombination: keine) |
    ;| |
    ;| Zweck : DeterminantenBerechnung einer quadratischen Matrix(z.B. vor einer Inversion) |
    ;| Quelle: mc (mehr weiß ich leider nicht mehr, sorry..) |
    ;+------------------------------------------------------------------------------------------+
    Global $Menu, $A, $d, $XL, $i, $j, $k
    Global $iDim, $MatFormat, $fw, $nk
    #Region ### START Koda GUI section ### Form=D:\Sprachen\AutoIt3\Au3\kxf\det.kxf
    $det=GUICreate('det', 815, 585, 191, 111)
    $grpMain=GUICtrlCreateGroup('', 0, -4, 813, 587)
    $lblTitel=GUICtrlCreateLabel('Determinantenberechnung', 6, 10, 469, 33)
    GUICtrlSetTip(-1, $Author)
    GUICtrlSetFont(-1, 18, 800, 0, 'Arial')
    GUICtrlSetColor(-1, 0x000080)
    $grpArt=GUICtrlCreateGroup('Eingabeart festlegen', 4, 42, 197, 53)
    $rbdatei=GUICtrlCreateRadio('Datei', 10, 58, 49, 17)
    $rbauto=GUICtrlCreateRadio('automatisch', 10, 76, 83, 17)
    $btnSuchen=GUICtrlCreateButton('Suchen', 119, 54, 75, 25, $WS_GROUP)
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    GUICtrlSetState(-1, $GUI_Hide)
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    $grpEingabe=GUICtrlCreateGroup('', 201, 42, 127, 53)
    GUICtrlSetState(-1, $GUI_Hide)
    $rbeingebaut=GUICtrlCreateRadio('eingebaute Matrix', 205, 58, 105, 17)
    GUICtrlSetState(-1, $GUI_Hide)
    $rbzufall=GUICtrlCreateRadio('Zufallsmatrix', 205, 76, 97, 17)
    GUICtrlSetState(-1, $GUI_Hide)
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    $grpmaxdim=GUICtrlCreateGroup('max. Dimension festlegen', 328, 42, 139, 53)
    GUICtrlSetState(-1, $GUI_Hide)
    $cmbmaxdim=GUICtrlCreateCombo('max', 370, 62, 53, 25)
    GUICtrlSetState(-1, $GUI_Hide)
    GUICtrlSetData(-1, '2|3|4|5|6|7|8|9|10|15|20')
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    $grpFormat=GUICtrlCreateGroup('Ausgabeformat', 624, 6, 185, 89)
    $lblvk=GUICtrlCreateLabel('Vorkommastellen', 634, 26, 50, 17)
    $cmbvk=GUICtrlCreateCombo('5', 724, 22, 81, 25)
    GUICtrlSetData(-1, '1|2|3|5|7', 5)
    $lblnk=GUICtrlCreateLabel('Nachkommastellen', 632, 49, 97, 17)
    $cmbnk=GUICtrlCreateCombo('5', 724, 46, 81, 25)
    GUICtrlSetData(-1, '1|2|3|4|5|6|7|8|9', 5)
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    $efMatrix=GUICtrlCreateEdit('', 4, 98, 805, 449)
    $btnBerechnen=GUICtrlCreateButton('Berechnen', 4, 553, 75, 27, $WS_GROUP)
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    $lbldet=GUICtrlCreateLabel('Determinante=', 82, 559, 82, 17)
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    $efdet=GUICtrlCreateInput('', 168, 557, 195, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY))
    GUICtrlSetBkColor(-1, 0xFFFFFF )
    $lblSoll=GUICtrlCreateLabel('Soll=', 368, 559, 28, 17)
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    $efSoll=GUICtrlCreateInput('', 398, 557, 149, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY))
    GUICtrlSetBkColor(-1, 0xFFFFFF )
    $lblDiff=GUICtrlCreateLabel('Soll-Ist=', 550, 559, 46, 17)
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    $efDiff=GUICtrlCreateInput('', 598, 557, 127, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY))
    GUICtrlSetBkColor(-1, 0xFFFFFF )
    $btnQuit=GUICtrlCreateButton('Quit', 734, 553, 75, 27, BitOR($BS_DEFPUSHBUTTON,$WS_GROUP))
    GUICtrlSetFont(-1, 8, 800, 0, 'MS Sans Serif')
    GUICtrlCreateGroup('', -99, -99, 1, 1)
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

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

    While 1
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE, $btnQuit
    Exit
    Case $btnBerechnen, $cmbvk, $cmbnk
    Berechnen()
    Case $rbdatei
    GUICtrlSetState($btnSuchen, $Gui_Show)
    GUICtrlSetState($rbzufall, $Gui_Hide)
    GUICtrlSetState($rbeingebaut, $Gui_Hide)
    GUICtrlSetState($grpEingabe, $Gui_Hide)
    GUICtrlSetState($grpmaxdim, $Gui_Hide)
    GUICtrlSetState($cmbmaxdim, $Gui_Hide)
    Case $rbauto
    GUICtrlSetState($btnSuchen, $Gui_Hide)
    GUICtrlSetState($rbzufall, $Gui_Show)
    GUICtrlSetState($rbeingebaut, $Gui_Show)
    GUICtrlSetState($grpEingabe, $Gui_Show)
    Case $rbzufall
    GUICtrlSetState($grpmaxdim, $Gui_Show)
    GUICtrlSetState($cmbmaxdim, $Gui_Show)
    GUICtrlSetData($efMatrix, '')
    GUICtrlSetData($efSoll, $XL)
    $XL=''
    Case $rbeingebaut
    GUICtrlSetState($grpmaxdim, $Gui_Hide)
    GUICtrlSetState($cmbmaxdim, $Gui_Hide)
    $iDim=6
    Dim $A[$iDim][$iDim]=[[0.659327444, 0.072983257, 0.979894657, 0.756750136, 0.25441669, 0.83763853], _
    [0.559241606, 0.523137874, 0.948388093, 0.330784887, 0.849705537, 0.169404574], _
    [0.933652887, 0.616332953, 0.217258497, 0.907022842, 0.082662047, 0.03529322], _
    [0.826041544, 0.765330767, 0.52478838, 0.158009727, 0.024860119, 0.36255325], _
    [0.846792095, 0.556488281, 0.48273207, 0.122986243, 0.059224104, 0.851249939], _
    [0.33697323, 0.625423359, 0.494137015, 0.130947714, 0.248825667, 0.928200963]]
    $XL=0.146436546
    GUICtrlSetData($efSoll, $XL)
    Berechnen()
    Case $cmbmaxdim
    $iDim=GUICtrlRead($cmbmaxdim)
    If $iDim<2 Or $iDim*1=0 Then
    $iDim=3
    Dim $A[$iDim][$iDim]=[[1, 2, 3], [4, 5, 6], [7, 8, 8]]
    $XL=3
    Else
    Dim $A[$iDim][$iDim]
    For $i=0 To $iDim-1
    For $j=0 To $iDim-1
    $a[$i][$j]=Random()
    Next
    Next
    $XL=''
    GUICtrlSetData($efDiff, $XL)
    EndIf
    GUICtrlSetData($efSoll, $XL)
    Berechnen()
    Case $btnSuchen
    $s='Die Eingabedatei MUSS eine reine Ascii-Datei sein!' &@CrLf
    $s&='In ihr stehen die Elemente der Matrix zeilenweise, jeweils durch 1 Leerzeichen getrennt' &@CrLf
    $s&='Dezimaltrennzeichen ist der Punkt(''.''), z.B. 12.345' &@CrLf &'Formatierungszeichen(Tausendertrennzeichen) sind nicht erlaubt..' &@CrLf
    $s&='Determinantenberechnung funktioniert nur bei quadratischen Matrizen' &@CrLf
    $s&='(für mathematisch weniger Bewanderte:Es müssen genausoviel Zeilen vorhanden sein, wie es Spalten gibt..)' &@CrLf
    $s&='Leerzeilen sind nicht erlaubt, sie würden als 0-Zeile gewertet und bewirken eine Determinante=0' &@CrLf
    $s&='Werden diese Bedingungen nicht eingehalten, errechnet das Programm Unsinn oder stürzt gar ab..' &@CrLf
    $s&='Für solche Bediener-Fehler bin ich nicht verantwortlich!' &@CrLf &'Wer das Programm benutzt, macht dies auf eigenes Risiko ;-))' &@CrLf
    GUICtrlSetData($efMatrix, $s)
    $n=FileOpenDialog('Datei suchen', @WorkingDir, 'Alle (*.*)', 1)
    If FileExists($n) Then $n=StringSplit(FileRead($n), @Lf)
    $iDim=$n[0]
    Dim $A[$iDim][$iDim]
    $k=''
    For $i=1 To $n[0]
    $s=StringSplit($n[$i], ' ')
    For $j=1 To $s[0]
    $a[$i-1][$j-1]=$s[$j]
    $k&=Stringformat('%-' &$fw &'.' &$nk &'f', $a[$i-1][$j-1])
    Next
    Next
    Berechnen()
    EndSwitch
    WEnd

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

    Func Berechnen()
    Local $i, $j, $vk=2, $nk=4, $s=''
    $nk=GuiCtrlRead($cmbnk)
    $fw=$nk+GuiCtrlRead($cmbvk)+1
    For $i=0 To UBound($A)-1
    For $j=0 To UBound($A)-1
    $s&=Stringformat('%-' &$fw &'.' &$nk &'f', $a[$i][$j])
    If $j<>(UBound($A)-1) Then
    $s&=' '
    Else
    $s&=@CrLf
    EndIf
    Next
    Next
    GUICtrlSetData($efMatrix, $s)
    $i=Determinante($A)
    If $i=0 Then $i&=' EXAKT NULL'
    GUICtrlSetData($efdet, $i)
    If GuiCtrlRead($efSoll)<>'' Then GUICtrlSetData($efDiff, StringFormat('%-8.5E', GuiCtrlRead($efSoll)-GuiCtrlRead($efdet)))
    EndFunc

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

    Func Determinante($A)
    Local $LftMat[$iDim][$iDim], $RgtMat[$iDim][$iDim], $d=1.0
    Local $i, $j, $k, $n=0
    $rgtmat[$n][$n]=$d
    $lftmat[$n][$n]=$A[$n][$n]
    For $k=$n To $iDim-1
    If $lftmat[$k][$k]=0.0 Then Return 0.0
    $i=$k+1
    For $j=$n To $k
    If $i<$idim Then ;kleine Schummelei, die in FreeBasic nicht nötig ist..
    $rgtmat[$j][$i]=($a[$j][$i]-Mpy($j-1, $j, $i, $lftmat, $rgtmat))/$lftmat[$j][$j]
    $lftmat[$i][$j]=$a[$i][$j]-Mpy($j-1, $i, $j, $lftmat, $rgtmat)
    $lftmat[$i][$i]=$a[$i][$i]-Mpy($k, $i, $i, $lftmat, $rgtmat)
    $rgtmat[$i][$i]=$d
    EndIf
    Next
    Next
    For $i=$n To $iDim-1
    $d*=$lftmat[$i][$i]
    Next
    $LftMat=0
    $RgtMat=0;Hilfsmatrizen löschen
    Return $d ;Funktionsergebnis zuweisen!!!
    EndFunc

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

    Func Mpy($i, $j, $k, $LftMat, $RgtMat) ;funktioniert nur mit Determinante() ZUSAMMEN..
    Local $m, $d=0.0
    For $m=0 To $i
    $d+=$lftmat[$j][$m]*$rgtmat[$m][$k]
    Next
    Return $d
    EndFunc

    [/autoit]


    Wer den FreeBasic-Quellcode möchte: hier klicken
    Viel Spaß beim Berechnen
    Gruß
    ytwinky

    (Ich) benutze stets die aktuelle (Beta) und SciTE..

  • Ich will nicht von deiner Funktion ablenken sondern nur für Interessierte weiter verweisen auf eine komplette AutoIt-Matrix-UDF wo unter anderem auch eine Funktion zur Berechnung der Determinante vorhanden ist: >>Matrix-UDF<<.

    P.S.: Da du so die Ausgleichungsrechnung erwähnst - zufällig ein Vermesser? :)

  • hi,
    schönen Dank für den Link, ich glaub, den hab ich noch nicht..
    @PS: Wenn du schonmal auf die linke Seite geschaut hast, wirst du unter meinem Nick auch eine Zeile finden, in der 'Beruf' steht UND genau darunter
    steht die Antwort auf deine Frage..
    Gruß
    ytwinky

    (Ich) benutze stets die aktuelle (Beta) und SciTE..

  • Hehe - ich hab mir ein GreaseMonkey-Skript gemacht womit ich im Forum alle unwichtigen und für mich überflüssigen Elemente raushaue (Signaturen, Shoutbox, Userränge etc.)
    Das war dann wohl das erste mal das sich da eine wichtige Information für mich verbarg.