1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • _ArrayDelete in For to Ubound

    • Mars
    • 20. Mai 2019 um 00:13

    Eine weitere Methode wäre folgendes:

    - Schiebe deine Werte die du behalten möchtest (inplace) nach vorne und die die du loswerden möchtest nach hinten.

    - Benutze genau 1x Redim auf dein nun strukturiertes Array und schneide dir damit den Teil aus den du behalten möchtest.

    Code
    #include <Array.au3>
    Global $a[5][3] = [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, 11, 12],[13, 14, 15]]
    _ArrayDisplay($a)
    ReDim $a[3][2] ; Redim Schneidet jeweils den Inhalt jedes Index' von 0 bis End aus.
    _ArrayDisplay($a)

    Der Code dient nur als Beispiel für das was ReDim macht.

    M

  • GDI+ DoppelPendel

    • Mars
    • 8. April 2019 um 12:56

    Ein Trick um das "ausufern" zu verhindern ist die Energieerhaltung.

    Zu Beginn berechnet man die Gesamtenergie (EPot + EKin) und nach jedem Frame (wenn alle Werte vorliegen) berechnet sie ebenfalls. Da es immer kleine Abweichungen gibt (man kann kein kontinuierliches system fehlerfrei diskret simulieren) wird die Gesamtenergie im System nicht erhalten sein. Jetzt passt man nach jedem Frame die Werte etwas an, sodass die Energie trotzdem erhalten bleibt. Das ist zwar eigentlich grober Unfug, hilft aber dabei das ein System nach einiger Zeit immernoch stabil (wenn auch falsch) läuft.

    kleiner Tip hier: (tooltip mit Energie (die kartesisch berechnet wurde... ist mir auch erst im nachhinein aufgefallen dass das doof ist :D))

    Spoiler anzeigen
    C
    #Region Includes
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <Color.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>
    #EndRegion
    
    
    #Region Declarations
    ;~ Window
    Global $wWidth = 800
    Global $wHeight = 600
    Global $wMiddle_x = $wWidth / 2
    Global $wMiddle_y = $wHeight / 2
    Global $middle_x = @DesktopWidth/2
    Global $middle_y = @DesktopHeight/2
    
    ;~ Env
    Global $pi = 3.141592653589793
    Global $g = 1
    Global $x[3], $y[3], $th[3], $v[3], $a[3], $l[3], $m[3], $oldX[3], $oldY[3]
    Global $energy
    
    ;~ INIT pendulum 1
    $l[1] = 200
    $m[1] = 20
    $th[1] = 0.4*$pi
    $v[1] = 0.0
    $a[1] = 0
    $x[1] = $wMiddle_x + $l[1] * sin($th[1])
    $y[1] = 0.5*$wMiddle_y - $l[1] * cos($th[1])
    
    ;~ INIT pendulum 2
    $l[2] = 200
    $m[2] = 20
    $th[2] = 0.5*$pi
    $v[2] = 0.0
    $a[2] = 0
    $x[2] = $x[1] + $l[2]*sin((($th[2]-180)*$pi)/180)
    $y[2] = $y[1] - $l[2]*cos((($th[2]-180)*$pi)/180)
    
    $oldX[1] = $x[1]
    $oldY[1] = $y[1]
    $oldX[2] = $x[2]
    $oldY[2] = $y[2]
    $energy = _Energy()
    ConsoleWrite('Startenergie: ' & $energy & @CRLF)
    #EndRegion
    
    
    #Region Gui
    $hGui = GUICreate("Form1", $wWidth, $wHeight, $middle_x-($wWidth/2), $middle_y-($wHeight/2),-2147483648)
    GUISetState(@SW_SHOW)
    #EndRegion
    
    
    #Region ### START GDI+ ###
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)
    
    ;~ Bitmaps
    $hGraphicBitmap = _GDIPlus_BitmapCreateFromGraphics($wWidth, $wHeight, $hGraphic)
    $hHistoryBitmap = _GDIPlus_BitmapCreateFromScan0($wWidth, $wHeight)
    $hLegBitmap = _GDIPlus_BitmapCreateFromScan0($wWidth, $wHeight)
    
    ;~ Buffers
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hGraphicBitmap)
    $hHistoryBuffer = _GDIPlus_ImageGetGraphicsContext($hHistoryBitmap)
    $hLegBuffer = _GDIPlus_ImageGetGraphicsContext($hLegBitmap)
    
    ;~ Smoothing
    _GDIPlus_GraphicsSetSmoothingMode($hBuffer, 4)
    _GDIPlus_GraphicsSetSmoothingMode($hHistoryBuffer, 4)
    _GDIPlus_GraphicsSetSmoothingMode($hLegBuffer, 4)
    
    ;~ First Clearing
    _GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF)
    _GDIPlus_GraphicsClear($hHistoryBuffer, 0xFFFFFFFF)
    _GDIPlus_GraphicsClear($hLegBuffer, 0xFFFFFFFF)
    
    ;~ Pens
    $hPen = _GDIPlus_PenCreate(0xFF0000FF, 1)
    #EndRegion ### END GDI+ ###
    
    
    #Region EventMode
    Opt("GUIOnEventMode", 1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
    #EndRegion
    
    
    #Region Loop
    While 1
       _Calc()
       _Draw()
       _Energy()
    WEnd
    #EndRegion
    
    #Region Functions
    Func _Energy()
        ; Summe aus m*g*h + Summe aus 1/2 mv² (ob das so exakt stimmt ist erstmal egal)
        $e1 = $m[1] * $g * ($wHeight - $y[1]) + $m[2] * $g * ($wHeight - $y[2])
        $e2 = 0.5 * $m[1] * (($x[1] - $oldX[1])^2 + ($y[1] - $oldY[1])^2) +  + 0.5 * $m[2] * (($x[2] - $oldX[2])^2 + ($y[2] - $oldY[2])^2)
        ToolTip('EPot: ' & Round($e1) & @CRLF & 'EKin: ' & Round($e2) & @CRLF & 'E: ' & Round($e1 + $e2) & ' (' & Round(($e1 + $e2)/$energy, 2)*100 & '%)')
        Return $e1 + $e2
    EndFunc
    
    Func _Calc()
    ;~    Acceleration 1
       $num1 = -$g * (2*$m[1]+$m[2]) * sin($th[1])
       $num2 = -$m[2] * $g * sin($th[1]-2*$th[2])
       $num3 = -2 * sin($th[1]-$th[2]) * $m[2]
       $num4 = $v[2]*$v[2] * $l[2] + $v[1]*$v[1] * $l[1] * cos($th[1]-$th[2])
       $den = $l[1] * (2 * $m[1] + $m[2] - $m[2] * cos(2*$th[1]-2*$th[2]))
       $a[1] = ($num1 + $num2 + ($num3 * $num4)) / $den
    
    ;~    Acceleration 2
       $num1 = 2 * sin($th[1]-$th[2])
       $num2 = ($v[1]*$v[1] * $l[1] * ($m[1]+$m[2]))
       $num3 = $g * ($m[1]+$m[2]) * cos($th[1])
       $num4 = $v[2]*$v[2] * $l[2] * $m[2] * cos($th[1]-$th[2])
       $den = $l[2] * (2 * $m[1] + $m[2] - $m[2] * cos(2*$th[1]-2*$th[2]))
       $a[2] = ($num1 * ($num2 + $num3 + $num4)) / $den
    
    ;~    Angles
       $v[1] += $a[1]
       $v[2] += $a[2]
       $th[1] += $v[1]
       $th[2] += $v[2]
    
    ;~    EndPoints
        $oldX[1] = $x[1]
        $oldY[1] = $y[1]
        $oldX[2] = $x[2]
        $oldY[2] = $y[2]
       $x[1] = $wMiddle_x - $l[1] * sin($th[1])
       $y[1] = 0.5*$wMiddle_y + $l[1] * cos($th[1])
       $x[2] = $x[1] - $l[2]*sin($th[2])
       $y[2] = $y[1] + $l[2]*cos($th[2])
    EndFunc
    
    
    Func _Draw()
    ;~    Clear
       _GDIPlus_GraphicsDrawImageRect($hLegBuffer, $hHistoryBitmap, 0, 0, $wWidth, $wHeight)
    
    ;~    Draw pieces
       _GDIPlus_GraphicsDrawLine($hLegBuffer, $wMiddle_x, 0.5*$wMiddle_y, $x[1], $y[1], $hPen)
       _GDIPlus_GraphicsFillEllipse($hLegBuffer, $x[1]-($m[1]/2), $y[1]-($m[1]/2), $m[1], $m[1])
       _GDIPlus_GraphicsDrawLine($hLegBuffer, $x[1], $y[1], $x[2], $y[2], $hPen)
       _GDIPlus_GraphicsFillEllipse($hLegBuffer, $x[2]-($m[2]/2), $y[2]-($m[2]/2), $m[2], $m[2])
    
    ;~    History
       _GDIPlus_GraphicsFillEllipse($hHistoryBuffer, $x[2], $y[2], 2, 2)
    
    ;~    Draw finally
       _GDIPlus_GraphicsDrawImageRect($hBuffer, $hHistoryBitmap,0, 0, $wWidth, $wHeight)
       _GDIPlus_GraphicsDrawImageRect($hBuffer, $hLegBitmap,0, 0, $wWidth, $wHeight)
       _GDIPlus_GraphicsDrawImageRect($hGraphic, $hGraphicBitmap, 0, 0, $wWidth, $wHeight)
    EndFunc
    
    
    Func _Exit()
       _GDIPlus_GraphicsDispose($hGraphic)
       _GDIPlus_PenDispose($hPen)
       _GDIPlus_Shutdown()
       Exit
    EndFunc
    #EndRegion
    
    
    #Region Event Functions
    Func SpecialEvents()
       Select
          Case @GUI_CtrlId = $GUI_EVENT_CLOSE
             GUIDelete()
             _Exit()
       EndSelect
    EndFunc
    #EndRegion
    Alles anzeigen
  • Info Studium MSc. Visual Computing oder Autonome Systeme ?

    • Mars
    • 20. März 2019 um 13:00

    Moin,

    ein paar hier wissen es sicher schon, aber ich bin ein oller Physik Student. Habe meinen BSc. vor 2 Jahren gemacht (mit ziemlich guter Note) und stecke jetzt irgendwo im Master Physik. Allerdings zieht sich das Studium ziemlich lang, vorallem weil mir alles so "weit weg" erscheint und ich alles was ich so lerne (Kernphysik, Quantenmechanik usw) nicht wirklich zu Hause anwenden kann (bin nicht so der Theoretiker in Physik) kurzum es ist zäh (zumindest aus meiner subjektiven Sicht). Der Bachelor ist aber sehr empfehlenswert, da lernt man wie die Welt funktioniert und hat eine Menge Spaß und Ärger, so wie sich das gehört.

    Nun habe ich mich entschieden Informatik MSc. zu machen, da ich denke dass ich hier wesentlich mehr Spaß haben kann und ansich bin ich auch besser im Programmieren und Herumbasteln (und in Informatik Theorie), als im komplizierte Formeln ineinander einsetzen und mit seltsamen Analysis Sonderfällen zu einer Lösung zu kommen, die man nur an einem Teilchenbeschleuniger nachprüfen kann.

    Da ich keine allgemeine Qualifikation für "alle" Info Studiengänge habe wurde mir Visual Computing und Autonome Systeme angeboten (ich kann eines dieser beiden Fächer als MSc. Studiengang wählen). Gibt es Leute die ggf. schon eines dieser Fächer machen/gemacht haben oder irgendwelche Erfahrungen darin haben? Es würde mich freuen eure Meinung zu hören, damit ich mich besser entscheiden kann, denn auf den ersten Blick sind beide Auswahlmöglichkeiten ziemlich interessant.

    (Edit: TU Darmstadt)

    Edit2: Es hat eine Woche niemand etwas dazu gesagt und ich schätze mal da kommt auch nichts mehr. Schade. Habe mich jetzt für Visual Computing entschieden.

    Edit3: Weil es superlustig ist hier zu Antworten: Jawohl, ich habe 2024 auch meinen Master in VC gemacht :D

    lg

    M

  • Adaptiver Huffman Encoder

    • Mars
    • 13. März 2019 um 20:10

    Die Zahlen darin sind eigentlich vollkommen wurscht :D

    Das Verfahren funktioniert so:

    - "Habe" eine Wahrscheinlichkeitstabelle für jedes Zeichen (wenn man nichts weiß ist das eine Gleichverteilung, oder in diesem Fall das Default Histogramm)

    - Baue einen Baum aus der Tabelle, Kodiere/Dekodiere ein Zeichen und erstelle damit die Tabelle neu. -> solange bis keine Zeichen übrig sind.

    Was du da reinschreibst ist also egal, alles was sich dadurch ändert ist die Kompressionsrate zu Beginn. Allerdings kann man keinen Text dekodieren, wenn eine andere Tabelle benutzt wurde als im Encoder, also könnte man dieses 256 float Gebilde als eine Art "viel zu langes Passwort" missbrauchen :D

    Max Mustermann, Musterbergheimer Landstraße 1 99, 12345 Musterbergheim am Musterberg.

    Edit: Falls jemand das Teil nochmal angesehen hat, ich habe den Min-Heap ergänzt, somit ist es jetzt ca. 30% schneller als vorher. Da es immernoch inplace in einem Array funktioniert kann man das 1:1 in jede beliebige Sprache genauso übernehmen und es müsste immer ziemlich effizient arbeiten. Außerdem habe ich TreeToLookup optimiert, sodass sie statt 3ms nur noch 2ms benötigt, leider immernoch rekursiv...

    lg

    M

  • BitShift (unsigned INT)

    • Mars
    • 13. März 2019 um 13:54

    Ich bin ein wenig verwirrt, die BitShift Funktion in AutoIt tut genau das was man vermuten würde oder?

    Poste doch bitte ein Skriptbeispiel das dein Problem reproduzieren kann (z.B. BitShift(abc, x) = 123, sollte aber eigentlich 234 sein). Dann kann man auch was damit anfangen und eine Lösung finden

    M

  • Adaptiver Huffman Encoder

    • Mars
    • 9. März 2019 um 12:52

    Hehehe,

    ich wollte die Sache erst "ADH = ADaptive Huffman" nennen, dann ist es aber "AHE = Adaptive Huffman Encoder" geworden. Wahrscheinlich wäre "AHC = Adaptive Huffman Code" noch besser. Namensfindung ist so kompliziert :(


    Den Baum aufspannen dauert (mit der jetzigen Methode) in AutoIt ca. 50ms. Schätze man kommt noch auf ca. 20-30ms wenn man ein wenig optimiert. Da ich alles so umgebaut habe, dass es inplace in einem Array stattfindet könnte man es 1 zu 1 in ASM übersetzen. Dann werden aus 20ms -> 20µs.

    //OT:

    Mit dem Internet stimmt wirklich etwas nicht. Ich wollte mir letztens einen Stream auf YT ansehen, der hat furchtbar gehackt ist andauernd stehengeblieben und konnte nur via F5 wieder für ein paar Sekunden am laufen gehalten werden. Dieses Totalversagen schiebe ich aber auf die Software. Meine Leitung hat einen Ping von ca. 25ms und kann ca. 5MB/s (wenn sie gute Laune hat), ich erwarte dass ein Stream damit flüssig läuft :thumbdown:

  • Adaptiver Huffman Encoder

    • Mars
    • 9. März 2019 um 00:30

    Moin,

    (Gleich zu Beginn mal ein Wiki-Link, jeder der nicht weiß worum es geht sollte den ggf. erst durchgehen :))

    Einen Huffman Encoder kann vermutlich jeder basteln (ist ja nicht so schwer) wo ich aber häufig Probleme beobachtet habe ist der Part mit dem Abspeichern der Wahrscheinlichkeitstabelle. Es ist nämlich so, dass der Decoder im Regelfall den Huffman-Baum zum dekodieren benötigt.

    Beispiel:

    Wenn ich jetzt aber meinen Text: "Hallo Test 123" verwende gibt es ein großes Problem: Der Text besteht aus vielen verschiedenen Zeichen (es ist ja nicht "aaaaaaabbabaaaa" oder soetwas) die jeweils auch nicht allzuoft vorkommen (Leerzeichen x2 und "l" x2), egal in welcher optimierten Darstellung ich den Huffman-Baum abspeichere, er wird in jedem Fall mehr Speicher verbrauchen als mein eigentlicher Text. Wenn ich jetzt den kodierten Text + Baum benötige um wieder meinen ursprünglichen Text zu erhalten ist nichts gewonnen. Hier kommt der adaptive Teil zum tragen.

    Ein adaptiver Kodierer beginnt mit irgendeiner vorgegebenen Wahrscheinlichkeitsverteilung (z.B. eine Gleichverteilung, dann hat jedes Zeichen beim erstmaligen auftreten 8 Bit, da es 256 theoretisch mögliche Asc Zeichen gibt), generiert daraus den Huffman-Baum und kodiert damit nur das allererste Zeichen des Textes. Dann wird dieses Zeichen mit einem gewissen Faktor zur Wahrscheinlichkeitstabelle hinzugefügt, ein neuer Baum generiert und damit das 2te Zeichen kodiert. usw usw. Das bedeutet, dass der Decoder KEINEN Baum benötigt, da dieser implizit durch die kodierte Nachricht selbst mitgeliefert wird. Das hat eine ganze Reihe Vor- und Nachteile.

    Vorteile:

    - Funktioniert auch für kurze Texte deren Huffman-Baum alleine schon größer wäre als der Text selbst

    - Falls man eine Dämpfung festlegt (in meinem Skript nicht enthalten) ist es möglich dass der Kodierer lokal besser arbeitet als wenn für den vollen Text die gleiche Verteilung angenommen werden würde.

    - Da die Wahrscheinlichkeitsverteilung laufend angepasst wird kann man von einem beliebigen Startpunkt aus loslaufen. Eine Gleichverteilung, oder ein Histogramm aller Zeichen in meinem UDF-Ordner, oder der Buchstabenverteilung in irgendeiner Sprache. In diesem Fall müsste man dem kodierten Text z.B. 2 bit voranstellen damit der Decoder weiß welche Verteilung er als Startwert nehmen soll. Man könnte auch die nicht adaptive Version so verwenden und statt einem Baum nur eine Baumnummer in den kodierten Text schreiben. Das wäre aber bei weitem suboptimaler, da dieser Baum dann nicht angepasst werden würde und man nicht für jeden beliebigen Text einen gut passenden Baum im Decoder hinterlegen kann. Eine Hand voll Verteilungen reichen bei der adaptiven Version aber vollkommen aus um immer ein gutes Ergebnis zu erzielen.

    Nachteile:

    - Da nach JEDEM ZEICHEN alles neu aufgebaut werden muss ist diese Methode unglaublich langsam (eine Version mit Min-Heap bastele ich gerade bin aber noch nicht zufrieden).

    - Da die Wahrscheinlichkeitstabelle laufend angepasst wird ist sie zu keinem Zeitpunkt "wirklich" optimal. Verglichen mit einem "normalen" Huffman-Code ist die adaptive Version je nach situation unterlegen und erzeugt längeren Output als notwendig.

    - Der Textanfang wird zwangsweise suboptimal kodiert, da die Startverteilung (z.B. die Gleichverteilung) nicht immer gut auf die vorliegende Zeichenfolge passt.

    - Habe ich langsam schon erwähnt? (auf meinem PC aktuell ca. 20-25 Zeichen/Sekunde)

    Villeicht kann ja jemand das Skript gebrauchen, daher landet es hier :)

    Edit: 12.03.19:

    Jetzt funktioniert das ganze mit Min-Heap und ist ca. 30% schneller als vorher. Es hat viel Spaß gemacht das Teil im Rahmen der Geschwindigkeit von AutoIt zu optimieren. Wenn man die Methode aber tatsächlich auch benutzen will sollte man es in einer anderen Sprache tun... 30 Zeichen/Sek ist unzureichend, alleine diesen Post hier zu kodieren würde ne Stunde dauern :D

    Code
    ; ### Adaptive Huffman Kodierung
    
    ; ### Start mit der Zeichenverteilung einiger Posts aus dem AutoIt.de Forum
    Global $__AHE_aHistDefault = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1360, 15, 85, 0, 0, 1, 0, 0, 17, 20, 3, 1, 73, 29, 74, 23, 11, 4, 12, 1, 0, 4, 1, 0, 8, 3, 17, 0, 0, 0, 0, 16, 0, 15, 44, 5, 52, 36, 12, 11, 25, 25, 3, 9, 15, 31, 24, 9, 17, 0, 9, 33, 36, 9, 27, 17, 0, 1, 21, 0, 0, 0, 3, 0, 0, 465, 145, 234, 365, 1279, 89, 202, 298, 635, 24, 110, 335, 271, 741, 225, 78, 3, 484, 426, 486, 276, 64, 97, 21, 3, 77, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 33, 0, 0, 0]
    For $i = 0 To UBound($__AHE_aHistDefault) - 1 Step 1
        $__AHE_aHistDefault[$i] /= 100
    Next
    
    ; ### Start mit einer Gleichverteilung
    ;~ Global $__AHE_aHistDefault[256]
    
    Global $__AHET[512][3]
    Global $__AHEE
    
    ;~ Local $sString = 'Ich bin ein etwas längeres Beispiel. Wenn man mit der Gleichverteilung gestartet ist sollte man hier den adaptiven Effekt gut beobachten können.'
    Local $sString = 'Ich bin ein Beispiel.'
    
    ConsoleWrite(@CRLF & '!----- Adaptive Huffman Entropiekodierung -----!' & @CRLF)
    
    ConsoleWrite('Input:  ' & $sString & @CRLF & 'Encode: ')
    Local $t = TimerInit()
    Local $sEnc = Huff_Encode($sString)
    $t = TimerDiff($t)
    ConsoleWrite(@CRLF & 'Output: ' & $sEnc & @CRLF & 'Bits:   ' & StringFormat('%.2f', StringLen($sEnc)/StringLen($sString)) & ' per Char' & @CRLF & @CRLF)
    
    ConsoleWrite('Input:  ' & $sEnc & @CRLF & 'Decode: ')
    Local $t = TimerInit()
    Local $sDec = Huff_Decode($sEnc)
    $t = TimerDiff($t)
    ConsoleWrite(@CRLF & 'Output: ' & $sDec & @CRLF & @CRLF)
    
    Func Huff_Encode(ByRef $sString)
        Local $aLookup[256], $aSymHist[256], $sRet = ''
        For $i = 0 To 255 Step 1
            $aSymHist[$i] += $__AHE_aHistDefault[$i] + 0.1 ; hier könnte man eine vorgegebene Wahrscheinlichkeit/Zeichen angeben
        Next
        Local $aTimers[2][2], $t
        For $i = 0 To StringLen($sString) - 1 Step 1
            $t = TimerInit()
            __AHE_BuildTreeFromSymbolHistogram($aSymHist)
            $aTimers[0][0] += TimerDiff($t)
            $aTimers[0][1] += 1
            $t = TimerInit()
            __AHE_TreeToLookupRec($aLookup)
            $aTimers[1][0] += TimerDiff($t)
            $aTimers[1][1] += 1
            ConsoleWrite($aLookup[Asc(StringMid($sString, $i + 1, 1))] & '(' & StringMid($sString, $i + 1, 1) & ') ')
            $sRet &= $aLookup[Asc(StringMid($sString, $i + 1, 1))]
            $aSymHist[Asc(StringMid($sString, $i + 1, 1))] += 8
        Next
        ConsoleWrite(@CRLF)
        ConsoleWrite('BuildTree: ' & StringFormat('%.1f', $aTimers[0][0] / $aTimers[0][1]) & ' ms' & @CRLF)
        ConsoleWrite('BuildLook: ' & StringFormat('%.1f', $aTimers[1][0] / $aTimers[1][1]) & ' ms' & @CRLF)
        Return $sRet
    EndFunc
    
    Func Huff_Decode($sString)
        Local $aLookup[256], $aSymHist[256], $sRet = ''
        For $i = 0 To 255 Step 1
            $aSymHist[$i] += $__AHE_aHistDefault[$i] + 0.1 ; hier könnte man eine vorgegebene Wahrscheinlichkeit/Zeichen angeben
        Next
        While $sString
            __AHE_BuildTreeFromSymbolHistogram($aSymHist)
            __AHE_TreeToLookupRec($aLookup)
            For $i = 0 To 255 Step 1 ; das ist dermaßen ineffizient, dass es fast wehtut. Das langsame Bottleneck ist aber __AHE_BuildTreeFromSymbolHistogram, weshalb
                If $aLookup[$i] = StringLeft($sString, StringLen($aLookup[$i])) Then ExitLoop ; ich diesen Teil hier nicht optimiert habe da er vernachlässigbar ist.
            Next
            $aSymHist[$i] += 8 ; habe einige Werte ausprobiert. Die 8 hat ganz gut performed
            ConsoleWrite($aLookup[$i] & '(' & Chr($i) & ') ')
            $sString = StringTrimLeft($sString, StringLen($aLookup[$i]))
            $sRet &= Chr($i)
        WEnd
        Return $sRet
    EndFunc
    
    Func __AHE_TreeToLookupRec(ByRef $aLookup, $i = 0, $sPath = '')
        If $__AHET[$i][2] = '' Then
            $aLookup[$__AHET[$i][0]] = $sPath
        Else
            __AHE_TreeToLookupRec($aLookup, $__AHET[$i][0], $sPath & '0')
            __AHE_TreeToLookupRec($aLookup, $__AHET[$i][2], $sPath & '1')
        EndIf
    EndFunc
    
    Func __AHE_BuildTreeFromSymbolHistogram(ByRef $aSymHist)
        Local $iRi = UBound($__AHET) - 1, $t, $n, $n2
        For $i = 0 To UBound($aSymHist) - 1 Step 1 ; Beginn von 0 bis 255 mit Leafs füllen
            $__AHET[$i][0] = $i             ; If Leaf: Char, Else LeftIndex
            $__AHET[$i][1] = $aSymHist[$i]  ; Propability
            $__AHET[$i][2] = ''             ; If Leaf: '', Else RightIndex
        Next
    
        $__AHEE = 256  ; Jemand rief "AHEEEEEE"  | Func BuildMinHeap()
        For $i = Int($__AHEE / 2) To 0 Step -1 ; | (wendet eigentlich nur Heapify auf das halbe Array an)
            $n = $i                            ; | Func Heapify()
            While 1                            ; |
                $t = 2 * $n                    ; |
                $n2 = ($t < $__AHEE And $__AHET[$t][1] < $__AHET[$n][1]) ? $t : $n
                $t += 1                        ; |
                If $t < $__AHEE And $__AHET[$t][1] < $__AHET[$n2][1] Then $n2 = $t
                If $n2 = $n Then ExitLoop      ; |
                $t = $__AHET[$n][0]            ; | [0] = wichtig, den kopieren wir :D
                $__AHET[$n][0] = $__AHET[$n2][0];| [1] = wichtig, kann man auch kopieren
                $__AHET[$n2][0] = $t           ; | [2] = '' für alle Elemente, brauchen wir also hier nicht.
                $t = $__AHET[$n][1]            ; | Der Vorherige Arrayinhalt von [2] ist auch egal und muss nicht
                $__AHET[$n][1] = $__AHET[$n2][1];| überschrieben werden, da kann also sonstiger Unfug drinstehen.
                $__AHET[$n2][1] = $t           ; |
                $n = $n2                       ; |
            WEnd                               ; | EndFunc Heapify
        Next                                   ; | EndFunc BuildMinHeap
    
        For $i = 0 To 254 Step 1
            $__AHET[$iRi][0] = $__AHET[0][0]   ; | Func HeapRemoveMin()
            $__AHET[$iRi][1] = $__AHET[0][1]   ; |
            $__AHET[$iRi][2] = $__AHET[0][2]   ; | kombiniert mit Min ans Ende schieben
            $__AHEE -= 1                       ; | und Heapbedingungerneuern.
            $__AHET[0][0] = $__AHET[$__AHEE][0]; |
            $__AHET[0][1] = $__AHET[$__AHEE][1]; |
            $__AHET[0][2] = $__AHET[$__AHEE][2]; |
            $n = 0                             ; | Func Heapify()
            While 1
                $t = 2 * $n
                $n2 = ($t < $__AHEE And $__AHET[$t][1] < $__AHET[$n][1]) ? $t : $n
                $t += 1
                If $t < $__AHEE And $__AHET[$t][1] < $__AHET[$n2][1] Then $n2 = $t
                If $n2 = $n Then ExitLoop
                $t = $__AHET[$n][0]
                $__AHET[$n][0] = $__AHET[$n2][0]
                $__AHET[$n2][0] = $t
                $t = $__AHET[$n][1]
                $__AHET[$n][1] = $__AHET[$n2][1]
                $__AHET[$n2][1] = $t
                $t = $__AHET[$n][2]
                $__AHET[$n][2] = $__AHET[$n2][2]
                $__AHET[$n2][2] = $t
                $n = $n2                       ; | EndFunc Heapify
            WEnd ; ----------------------------- | EndFunc HeapRemoveMin
    
            $__AHET[$iRi-1][0] = $__AHET[0][0] ; | Func HeapRemoveMin()
            $__AHET[$iRi-1][1] = $__AHET[0][1] ; | Nochmal. wir wollen ja die 2 kleinsten Elemente.
            $__AHET[$iRi-1][2] = $__AHET[0][2]
            $__AHEE -= 1
            $__AHET[0][0] = $__AHET[$__AHEE][0]
            $__AHET[0][1] = $__AHET[$__AHEE][1]
            $__AHET[0][2] = $__AHET[$__AHEE][2]
            $n = 0                             ; | Func Heapify()
            While 1
                $t = 2 * $n
                $n2 = ($t < $__AHEE And $__AHET[$t][1] < $__AHET[$n][1]) ? $t : $n
                $t += 1
                If $t < $__AHEE And $__AHET[$t][1] < $__AHET[$n2][1] Then $n2 = $t
                If $n2 = $n Then ExitLoop
                $t = $__AHET[$n][0]
                $__AHET[$n][0] = $__AHET[$n2][0]
                $__AHET[$n2][0] = $t
                $t = $__AHET[$n][1]
                $__AHET[$n][1] = $__AHET[$n2][1]
                $__AHET[$n2][1] = $t
                $t = $__AHET[$n][2]
                $__AHET[$n][2] = $__AHET[$n2][2]
                $__AHET[$n2][2] = $t
                $n = $n2                       ; | EndFunc Heapify
            WEnd ; ----------------------------- | EndFunc HeapRemoveMin
    
            $__AHET[$__AHEE][0] = $iRi         ; | Func HeapInsert(NewNode)
            $__AHET[$__AHEE][1] = 1 / 0        ; | Aus den vorher gefundenen 2 kleinsten Elementen entsteht
            $__AHET[$__AHEE][2] = $iRi - 1     ; | eine neue Node die man per Insert in den Heap stopft.
            $n = $__AHEE                       ; | Func HeapDecrease()
            If $__AHET[$n][1] >= $__AHET[$iRi][1] + $__AHET[$iRi - 1][1] Then
                $__AHET[$n][1] = $__AHET[$iRi][1] + $__AHET[$iRi - 1][1]
                While $n > 0 And $__AHET[$n][1] < $__AHET[Int($n / 2)][1]
                    $n2 = Int($n/2)
                    $t = $__AHET[$n][0]
                    $__AHET[$n][0] = $__AHET[$n2][0]
                    $__AHET[$n2][0] = $t
                    $t = $__AHET[$n][1]
                    $__AHET[$n][1] = $__AHET[$n2][1]
                    $__AHET[$n2][1] = $t
                    $t = $__AHET[$n][2]
                    $__AHET[$n][2] = $__AHET[$n2][2]
                    $__AHET[$n2][2] = $t
                    $n = $n2
                WEnd
            EndIf                              ; | EndFunc HeapDecrease
            $__AHEE += 1                       ; | EndFunc HeapInsert
            $iRi -= 2 ; Reverse Index - 2
        Next
    EndFunc
    Alles anzeigen

    lg

    M

  • NativeAutoItObjectEx (Objekte in AutoIt)

    • Mars
    • 5. März 2019 um 15:27

    Vielen Dank für das Lob, ich mache immer viel zu viele Sachen gleichzeitig, weshalb einiges oft für Ewigkeiten auf der Strecke bleibt...

    Vermutlich werde ich eines schönen Tages die Vorschläge von BugFix umsetzen, das wäre ansich schon wichtig. Außerdem gibt es noch ein paar Bugs/Aufräumarbeiten...

    Für GDI+ "Objekte" kannst du den Datentyp ptr nutzen (denn nichts anderes sind die "hGFX" und "hBMP" und so weiter, alles nur Pointer auf ein Stückchen Speicher).

    lg

    M

  • Quoted-Printable Kodierung zu UTF-8 konvertieren (St=C3=B6rung - Störung)

    • Mars
    • 20. Februar 2019 um 18:21

    Interessant. Man wird jeden Tag ein kleines Stückchen schlauer :D

    Ich tendiere ja persönlich dazu inzwischen alles als HexString (UTF8) zu übertragen/speichern/sonstiges, denn 0-9A-F bekommt jedes Format einwandfrei hin (natürlich braucht man dann mehr Bandbreite/Speicher, weil man doppelt so viele Zeichen hat, aber es funktioniert wenigstens (meistens... manchmal denkt sich ein Programm auch, hey lass mal spontan irgendwelche Bytes rückwärts lesen, dann muss man kurz eine Schelle mit der Rückhand austeilen und dann gehts wieder)). Ansich finde ich es bescheuert, dass es überhaupt so viele Kompatibilitätsprobleme und den Bedarf an Umkodierern gibt... Ich will einfach die guten Alten ASC Zeiten wieder haben, da war Text noch eine Art "primitiver Datentyp" der durch seine Bits unmissverständlich eindeutig definiert war...

    Villeicht werde ich beim nächsten Mal wo ich auf soetwas stoße auch hier nachlesen wie das mit den verschieden kodierten Texten aussieht... mal schauen :D

    M

  • Diskussion zum Thema : "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    • Mars
    • 19. Februar 2019 um 22:37

    Ich finde diese Reihenfolgen vollkommen nachvollziehbar. Bei einer GUI will ich zu allererst einmal die Größe bestimmen (wo sie genau ist ist in 90% aller Fälle egal), bei einem Ctrl will ich zuerst den Ort bestimmen.

  • Diskussion zum Thema : "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    • Mars
    • 14. Februar 2019 um 23:33

    Hey, du bist der Boss :D

    Jetzt habe ich schon 2 Verbesserungsvorschläge für meinen Beitrag bekommen 8)

    Dann nehme ich jetzt den Text von Bitnugger, das Codebeispiel von Dir mit der Zahl 5.5 :P

  • Sammelthread "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    • Mars
    • 14. Februar 2019 um 16:33

    Wird Round() in Kombination mit Funktionen verwendet, die je nach Datentyp unterschiedlich agieren (z.B. Hex(5) <> Hex(5.0)), kann es zu unerwarteten Ergebnissen führen, da Round() als Rückgabetyp immer ein Double liefert, sofern der optionale Parameter "decimalplaces" mit angegeben wird - wird dieser weggelassen, ist der Rückgabetyp immer Int32.

    Code
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Die Verwendung des optionalen Parameters "decimalplaces" führt zur Rückgabe unterschiedlicher Datentypen : ' & @CRLF)
    ConsoleWrite('! Datentyp ohne "decimalplaces" -> Round(5.5)    = ' & VarGetType(Round(5.5)) & @CRLF)
    ConsoleWrite('! Datentyp mit "decimalplaces"  -> Round(5.5, 0) = ' & VarGetType(Round(5.5, 0)) & @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)
    ConsoleWrite('+ Beispiel mit der Funktion Hex(), wo der Datentyp den Rückgabewert beeinflusst : ' & @CRLF)
    ConsoleWrite('! Hex mit Round(5.5)    = ' & Hex((Round(5.5))) & @CRLF)
    ConsoleWrite('! Hex mit Round(5.5, 0) = ' & Hex((Round(5.5, 0))) & ' (Anm.: Hex-Repräsentation einer Gleitkommazahl)'& @CRLF)
    ConsoleWrite('+ --------------------------------------------------------------------------------------------------------- ' & @CRLF)

    Edit: Rechtschreibung und Formulierung und Code :D

    M

  • Diskussion zum Thema : "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    • Mars
    • 14. Februar 2019 um 14:24

    Ceiling, Floor oder Int sind manchmal nicht die beste Wahl, vorallem wenn man Gleitkommarechnungen hat und "runden" möchte (und nicht ab- oder aufrunden).

    Der eigentlich interessante Teil ist das mit Int32 und Double als Returnwert der selben Funktion, je nachdem ob man mit- oder ohne Parameter auf 0 Kommastellen rundet, obwohl man eigentlich in beiden Fällen Int32 ODER Double erwarten würde (als jemand der auch andere Sprachen nutzt erwartet man in beiden Fällen Double)

  • Diskussion zum Thema : "AutoIt Interne Funktionen : Erwartetes Ergebnis -> Tatsächliches Ergebnis"

    • Mars
    • 14. Februar 2019 um 11:17

    Wer gerne Round benutzt und häufiger ins Hexadezimalsystem vorstößt hat sich sicher schon über Hex(Int(Round($a, 0)), 2) geärgert (also dass man DREI Funktionen braucht um aus 125.5 ein 7E zu machen). Lustigerweise gibt Round($a, 0) ein Double, während Round($a) ein Int32 ausspuckt. Will man also Hex(Round($a)) hat man keine Probleme, solange man die Null weglässt (die ich intuitiv immer erstmal hinmache)

    Code
    Local $a = 125.5
    ConsoleWrite(VarGetType(Round($a)) & @CRLF)
    ConsoleWrite(VarGetType(Round($a, 0)) & @CRLF)
    ConsoleWrite(Hex(Round($a), 2) & @CRLF)
    ConsoleWrite(Hex(Round($a, 0), 2) & @CRLF)

    lg

    M

  • Abspielen zweier Videos (synchron) mittels FFmpeg

    • Mars
    • 13. Februar 2019 um 20:08

    Threadtitel geändert von "Ich sitze vor AutoIt und verstehe nichts" zu "Abspielen zweier Videos (synchron) mittels FFmpeg" damit die Übersicht erhalten bleibt und man am Titel schon erkennen kann um was es geht :)

    lg

    M

  • Matrix Multiplikation Rückwärts

    • Mars
    • 10. Februar 2019 um 19:15

    Moin,

    Jeder Kennt die Matrixmultiplikation A * B = C, man kennt A und B und sucht C. Einfache Sache.

    Was passiert aber, wenn man A * B = C hat und B und C kennt und A sucht?

    Ich bin leider kein Meister der linearen Gleichungssysteme und habe jetzt einige Zeit probiert dazu eine anständige (analytische) Lösung zu programmieren, einige Erkenntnisse liste ich hier auf, vllt hilft das jemandem weiter. Ansich suche ich aber jemanden der zu viel Freizeit, oder bereits eine Lösung für dieses Problem parat hat.

    Wofür brauche ich das?

    Ich habe in der letzten Zeit versucht eine Art "Texterkennung" zu basteln die auch mit Pixelfehlern usw. klarkommt. Dabei sind die Inputpixel (Schwarz oder Weiß, 0 oder 1) jeweils eine Spalte in der Matrix B. Jede Zeile steht für die Erkennungspixel eines einzelnen Zeichens, (vereinfacht (als 3x3 Pixel "Bit"map) 010 010 010 = "I", 111 101 111 = "O", usw usw). In C stehen jetzt die zugeordneten Zeichen als Zeile, z.B. kommt soetwas heraus wie [0.123, 0.013, -1.5, 1], dann weiß man, dass die untersuchte Bitmap wahrscheinlich das Zeichen Nummer 4 ist (die Zuordnung welches Zeichen welche Nummer hat passiert woanders). Der Knackpunkt ist die Matrix A die quasi die "Gewichtung" der einzelnen Pixel für die einzelnen Zeichen beinhaltet. Vereinfacht: Ist der obere Linke Pixel = Schwarz, so ziehe ich vom Buchstaben O etwas ab da er unwahrscheinlich ist und Addiere bei W, T, P usw etwas dazu, weil diese Buchstaben wahrscheinlicher sind. Nachdem man also die Volle Multiplikation von A = Gewichtungsmatrix * B = "Bit"map durchgeführt hat weiß man welches Zeichen in der Bitmap steht. Vorteil bei der Geschichte ist folgendes: Selbst wenn ein paar Pixel falsch sind (weil z.B. die Kantensuche bei unterschiedlichen Farben für unterschiedliche Ergebnisse beim gleichen Buchstaben sorgt) haben die restlichen Pixel immernoch genug Informationen um den Buchstaben anständig zuzuordnen. Durch die Gewichtung ist diese Methode auch einem direkten Vergleich mit einer Testbitmap überlegen (außerdem müsste man dann alle theoretisch möglichen Zeichen 1x vergleichen und das mit der niedrigsten Abweichung ist dann das richtige, das ist zwar mathematisch einfacher, aber unnötig Rechenaufwändig und niemand will ein paar hundert Bitmaps haben).

    Problemstellung: A * B = C

    - A - Unbekannt <- Soll berechnet werden

    - B - Bekannt (Mögliche Werte sind 0, 1)

    - C - Bekannt (Mögliche Werte sind -1, 0, 1. Das -1 kommt vom OffsetVektor für ein komplett leeres B, da A * 0 = 0 ist, ein leeres B aber z.B. für ein Leerzeichen stehen kann, also muss C <> 0 sein)

    Erkenntnisse:

    - Die Lösung wäre Trivial, wenn A quadratisch wäre sodass man A invertieren kann. Da A aber beliebige Maße haben können muss ist das nicht möglich.

    - B[n][m] und C[k][m] bedeutet A[k][n] -> also ist A automatisch A[UBound(C, 1)][UBound(B, 1)]

    - Es gibt nicht immer eine Lösung (vorallem bei kleinen Matrizen die in meinem Anwendungsfall nicht vorkommen werden, genauso wie ein Inputvektor mit nur Nullen, oder ein Outputvektor mit nur Nullen, jede Matrix Zeile/Spalte hat immer mindestens einen von 0 verschiedenen Wert)

    - Es gibt, wenn es eine Lösung gibt (fast immer) unendlich viele Lösungen, da das Gleichungssystem (fast immer) überbestimmt ist, bzw. Werte voneinander abhängen (wenn man an beiden dreht bleibt das Ergebnis gleich). A enthält viel mehr Werte als es Gleichungen gibt. Für eine optimale Nutzung wäre natürlich eine Art "Durchschnittslösung" die best mögliche Lösung. Man kann also nicht einfach alle "überflüssigen" Werte aus A = 0 setzen und mit dem Rest das System lösen, das ruiniert die Fehlerkorrektur, weil es den Einfluss einzelner Pixel (einzelner Elemente aus B) auf das Ergebnis maximiert un der soll ja gerade minimiert werden.

    Beispielskript:

    Das Skript macht folgendes:

    1. Fülle A mit Zufallszahlen

    2. Suche ein Zufälliges Element aus A heraus, speichere dessen Wert und Addiere eine kleine Zufallszahl

    3. Berechne Abweichung(A * B, C)

    4. Schaue ob die Abweichung kleiner geworden ist:

    wenn ja -> Weiter zuSchritt 2.

    wenn nein -> Mache die Änderung des Elements rückgängig und dann weiter zu Schritt 2.

    5. Ist die Abweichung kleiner als irgendein Epsilon -> Höre auf

    6. Wird die Abweichung nie kleiner als ein Epsilon > 0, dann gibt es keine exakte Lösung. In dem Fall wird "eine" Approximation der Lösung generiert (die aber bei kleinen Matrizen meistens Müll ist, bei großen ist sie aber ziemlich gut).

    So das wars von mir. Wenn jemand Ideen, Skripte oder anderweitiges hat um A * B = C nach A aufzulösen, her damit!

    Edit: 12.2.19:

    Teile Des Systems sind unabhängig lösbar. Also es reicht eigentlich ein u * B = v zu lösen, wobei u,v = Vektoren sind.

    Dabei treten die Fälle auf:

    1. Es gibt mehr Gleichungen als Variablen -> Best Match gesucht (also ein u finden, sodass v möglichst gut quadratisch approximiert wird), hier gibt es ggf. ein Verfahren von Gauß (wie für alles in der Welt) in das ich mich noch einlesen muss.

    2. Es gibt gleich viele Gleichungen wie Variablen -> Trivial (Andys Gleichungssystemlöser freut sich)

    3. Es gibt mehr Variablen als Gleichungen -> "Durchschnittslösung" gesucht (für kleine Systeme habe ich hier eine Lösung, z.B. a + b = 1, die "Durchschnittslösung" ist hier a = b = 0.5. Da man hier immer Variablen paarweise gleichsetzt hat man aber eine Fakultät in der Anzahl Terme die man berechnen muss, für z.B. 20 variablen und 10 Gleichungen wären das 20!/10 = 2.4e17 Terme, was schon nicht mehr praktikabel ist...)

    Code
    #include <Array.au3>
    
    ; Hierfür gibt es keine Lösung für A
    ;~ Local $B = [[0, 0, 0], [0, 1, 0], [0, 0, 0], [1, 1, 1]]
    ;~ Local $C = [[1, 0, -1], [0, 1, 1]]
    
    ; Hierfür gibt es unzählige Lösungen für A, z.B. [[-1, 1, 1, 0], [1, 0, 0, 0]]
    Local $B = [[0, 1, 1], [1, 0, 0], [0, 1, 0], [1, 1, 1]]
    Local $C = [[1, 0, -1], [0, 1, 1]]
    
    ;~ Local $ADefault = [[-1, 1, 1, 0], [1, 0, 0, 0]] ; Ich bin eine Exakte Lösung für den 2ten Fall
    Local $ADefault = False
    Local $A = IDontKnow($B, $C, $ADefault) ; Ich bin Zufällig
    
    _ArrayDisplay($A, 'A[' & UBound($A, 1) & '][' & UBound($A, 2) & ']')
    _ArrayDisplay($B, 'B[' & UBound($B, 1) & '][' & UBound($B, 2) & ']')
    _ArrayDisplay($C, 'C[' & UBound($C, 1) & '][' & UBound($C, 2) & ']')
    
    Local $CompareC = MatrixMultiply($A, $B)
    
    _ArrayDisplay($CompareC, 'CompareC[' & UBound($CompareC, 1) & '][' & UBound($CompareC, 2) & ']')
    
    Func IDontKnow(ByRef $B, ByRef $C, $ADefault = False) ; A * B = C, berechne A
        If UBound($B, 2) <> UBound($C, 2) Then Return SetError(1, 1, 0)
        Local $A[UBound($C, 1)][UBound($B, 1)]
    
        ; Hier kommt nur noch Unfug weil mir keine analytische Methode einfällt
    
        If IsArray($ADefault) Then ; Default
            $A = $ADefault
        Else ; A mit Zufallszahlen füllen
            For $i = 0 To UBound($A, 1) - 1 Step 1
                For $ii = 0 To UBound($A, 2) - 1 Step 1
                    $A[$i][$ii] = Random(-1, 1)
                Next
            Next
        EndIf
    
        Local $iRandomi, $iRandomii, $nOldElem
        Local $M = MatrixMultiply($A, $B)
        Local $nDif = Dif($M, $C), $nDifOld = $nDif
        Local $nEpsilon = 0.001, $nMax = 39999
    
        For $n = 0 To $nMax - 1 Step 1
            $iRandomi = Random(0, UBound($A, 1) - 1, 1)
            $iRandomii = Random(0, UBound($A, 2) - 1, 1)
            $nOldElem = $A[$iRandomi][$iRandomii]
            $A[$iRandomi][$iRandomii] += Random(-0.1, 0.1) * $nDif ^ 0.75
            $M = MatrixMultiply($A, $B)
            $nDif = Dif($M, $C)
            If $nDif > $nDifOld Then
                $A[$iRandomi][$iRandomii] = $nOldElem
            Else
                If $nDif < $nEpsilon Then ExitLoop
                $nDifOld = $nDif
                Tip(Round($n / ($nMax - 1), 2) * 100 & '%' & @CRLF & $nDif)
            EndIf
        Next
    
        For $i = 0 To UBound($A, 1) - 1 Step 1
            For $ii = 0 To UBound($A, 2) - 1 Step 1
                $A[$i][$ii] = Round($A[$i][$ii], Int(Log(1 / $nEpsilon)))
            Next
        Next
    
        ConsoleWrite('Found A to calculate C with R = ' & $nDif & @CRLF)
    
        ToolTip('')
        Return $A
    EndFunc   ;==>IDontKnow
    
    Func Tip($s)
        Local Static $t = TimerInit()
        If TimerDiff($t) < 100 Then Return
        $t = TimerInit()
        ToolTip($s)
    EndFunc   ;==>Tip
    
    Func Dif(ByRef $M1, ByRef $M2)
        Local $nDif = 0
        For $i = 0 To UBound($M1, 1) - 1 Step 1
            For $ii = 0 To UBound($M1, 2) - 1 Step 1
                $nDif += ($M1[$i][$ii] - $M2[$i][$ii]) ^ 2
            Next
        Next
        Return $nDif ^ 0.5
    EndFunc   ;==>Dif
    
    Func MatrixMultiply(ByRef $aA, ByRef $aB) ; A * B = C, berechne C
        If Not (IsArray($aA) And IsArray($aB)) Then Return SetError(1, 1, 0)
        If UBound($aA, 0) <> 2 Or UBound($aB, 0) <> 2 Then Return SetError(1, 2, 0)
        If UBound($aA, 2) <> UBound($aB, 1) Then Return SetError(1, 3, 0)
        Local $iR = UBound($aA), $iC = UBound($aB, 2), $iD = UBound($aA, 2), $iX, $aC[$iR][$iC]
        For $r = 0 To $iR - 1
            For $C = 0 To $iC - 1
                $iX = 0
                For $z = 0 To $iD - 1
                    $iX += $aA[$r][$z] * $aB[$z][$C]
                Next
                $aC[$r][$C] = $iX
            Next
        Next
        Return $aC
    EndFunc   ;==>MatrixMultiply
    Alles anzeigen

    lg

    M

  • Zahlen größer 64-bit ?

    • Mars
    • 3. Februar 2019 um 18:28

    Wenn es nicht allzu genau sein muss und die Zahlen wirklich exorbitant groß werden (millionen von Stellen groß) kannst du sie auch in der Form a * 10^b speichern (wobei a und b jeweils float64 sind). Dann müsstest du dir die Rechenarten (Add, Sub, Mul, Div, usw) zwar selbst basteln, aber das ist ziemlich einfach. Dabei verliert man natürlich die Genauigkeit, wenn man z.B. 10^500 - 10^10 rechnet wird sich da nicht viel ändern. Addition und Subtraktion funktionieren bis zu einem Unterschied von ca. 10 Kommastellen, Multiplikation und Division funktionieren immer.

  • NativeAutoItObjectEx (Objekte in AutoIt)

    • Mars
    • 10. Januar 2019 um 23:19

    Das geht hier auch nicht. Intern wird DllCallbackRegister genutzt um an Pointer für die Funktionen zu kommen die das Objekt dann verinnerlicht. Leider ist diese Funktion nicht ByRef Kompatibel und in der AutoIt-Hilfe/bzw. dem großen Internet steht auch kein Lösungsansatz.

    Man kann zwar via 'int*' eine Dllstruct ByRef verteilen (in dem Fall wird einfach der Pointer übergeben), AutoIt-Variablen scheinen aber AutoIt-Typisch eine Temporäre Struct zu bekommen deren Inhalt nach einer Neuzuweisung ignoriert wird.

    Villeicht übersehe ich auch irgendwas. Hier mein Beispielskript:

    Code
    Func Test($a)
        Local $v = DllStructCreate('int a', $a)
        $v.a += 1
        ConsoleWrite('im Call: ' & $v.a & @CRLF)
    EndFunc
    
    Local $a1 = 5
    Local $iCallback = DllCallbackRegister('Test', 'uint', 'int*')
    ConsoleWrite('CallbackRegisterError: ' & @error & @CRLF)
    If $iCallback Then
        DllCallAddress('uint', DllCallbackGetPtr($iCallback), 'int*', $a1)
        ConsoleWrite('Nach dem Call: ' & $a1 & @CRLF)
        DllCallbackFree($iCallback)
    EndIf
    Alles anzeigen

    (Man kann das Verhalten mit Structs nachbilden, da ist ByRef kein Problem, aber ich schätze mal das weißt du und das ist nicht was du suchst)

    Edit: Falls jemand DllStructCallbackRegister mit Byref hinbekommt kann ich das in die UDF einbauen.

    Außerdem habe ich einen Bug gefunden: Man MUSS Objektvariablen deklarieren (also mindestens eine) weil die UDF sonst abstürzt. Das schaue ich mir später nochmal an. Als Fix einfach Var('int abc') reinschreiben, dann geht alles.

    Edit2: Die UDF von ProgAndy & Friends baut auf einer mitgelieferten DLL auf und hat nichts mit dieser UDF hier zu tun (die ohne alles auskommt). Die Gundidee ist im Prinzip die selbe, nur die Methode wie man es in AutoIt wrappt ist unterschiedlich.

    M

  • NativeAutoItObjectEx (Objekte in AutoIt)

    • Mars
    • 8. Januar 2019 um 20:15

    Was bedeutet in diesem Kontext "ByRef". Also was genau soll ByRef übergeben werden können? Wenn du ein Objekt selbst meinst (also eine Funktion die als Parameter byref ein Objekt bekommt) kann ich mal herumprobieren.

    Edit: Da der Kern der UDF genau der selbe ist wie vorher gebe ich aber davon aus dass das Vorhaben nicht klappt.

    Man muss auch in Objekten $a = ObjP(xyz) und dann $a.method aufrufen, weil Autoit scheinbar die referenz killt sobald der Wert von etwas zurückgegeben wurde ohne zu beachten dass er ggf. noch weiterverwendet wird. Das könnte man natürlich damit umgehen, dass man das Objekt zwar ByRef übergibt, aber eine referenz irgendwo seperat abspeichert. Das prüfe ich aber heute nicht mehr.

  • NativeAutoItObjectEx (Objekte in AutoIt)

    • Mars
    • 8. Januar 2019 um 19:20

    Und direkt ein Doppelpost. Die UDF ist nun fertig. Habt Spaß damit.

    "fertig" bedeutet, dass ich davon ausgehe, dass die UDF im Kern ab jetzt Abwärtskompatibel bleibt. Skripte die heute Laufen sollten auch Morgen noch gehen.

    (Fehlermeldungen und Verbesserungsvorschläge sind gern gesehen)

    lg

    M

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™