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

  • DecToBin (Adaptive)

    • Mars
    • 9. Mai 2023 um 14:34

    Ich hab ja auf meinem PC schon einen AutoIt-Ordner mit unmengen Skripten die ich üblicherweise auch korrekt benenne. Aber das klappt auch nur, wenn man alles was man mit AutoIt macht grundsätzlich in diesen Ordner verschiebt und benennt/taggt. Der "adaptive" Teil ist in irgendeinem Skript wo ich das ausprobiert hatte, habe es aber nicht in die Dec2Bin UDF eingebaut, obwohl es da eigentlich hingehört.

    Ich glaube ich bastel noch eine "optimale" Version davon (der prefix wird via HuffmanTree ermittelt anstatt dass man ihn "pi mal Daumen" von Hand schätzt). Das wäre dann so:
    - Input: Wahrscheinlichkeit für 1, 2, ..., n Bit Zahlen (dann kann man den Huffman mit den Symbolen 1, 2, ..., n und den Wahrscheinlichkeiten p(1), p(2), ... p(n) laufen lassen)

    - Output: Prefixset das die benötigten Bits zur Darstellung dieser Zahlen minimiert.
    (wir sind hier aber immernoch mit "ganzen Bits ohne Übertrag" unterwegs, also wird der Prefix auf maximal 0.5 Bit optimal, außerdem werden Sonderstellungen (z.B. die Zahl 0 taucht echt oft auf, und sollte daher nicht als "prefix + bits", sondern direkt kodiert werden) nicht berücksichtigt, was im schlimmsten fall nochmal ein Bit pro Zahl schluckt... ). Immernoch weit vom Entropielimit entfernt, aber ein erster Ansatz.

    Edit: Ich bin ziemlich blöd... Habe irgendwann mal eine Base.au3 gebastelt (zur Umrechnung zwischen z.B. Base10 und Base2, vielleicht kennt man sie aus meiner Abgabe zum Kompressionswettbewerb, Februar 22 von Oscar). Dort war auch die Adaptive version... Warum hat mir die Windows Suche (die ja angeblich auch Dateiinhalte durchsucht) das nicht angezeigt? Muss ich den Ordner wirklich mit VS Code öffnen und dann suchen? Oh man...

    Edit2: Adaptive Version (Huff) ist im Startpost. Die wollte ich schon seit Ewigkeiten bauen und hab es immer nicht gemacht^^

    M

  • DecToBin (Adaptive)

    • Mars
    • 9. Mai 2023 um 12:27
    Zitat von Andy

    Du hängst doch mit dem "neuen" Dec2Bin nicht etwa an dem alten Thread von 2011?! :rofl:

    Ooooooh, ja... So findet man seinen alten Code wieder und wieder und wieder (in 10 verschiedenen threads) ^^
    Da ging es aber eher um "wie kann ich einen riesigen String aus Dezimalzahlen ins Hexadezimalsystem bringen".

  • DecToBin (Adaptive)

    • Mars
    • 8. Mai 2023 um 22:27

    Moin,

    bevor ich meine eigenen Skripte wieder verlege und nie wieder finde, lade ich sie lieber mal hoch, dann findet man sie im Notfall in der Suche ;)

    Anbei ist eine DecToBin UDF. Sie kann... Dezimalzahlen in Binärzahlen umwandeln und umgekehrt (vermutlich geistern davon 10 Versionen durchs Forum). Neulich habe ich die Adaptive Version davon gesucht und nicht mehr gefunden, der Aufbau ist trivial, also war es einfach dasselbe nochmal zu schreiben.

    Die UDF ist von 2014 (im Prinzip sogar noch älter, aber ich habe irgendwann mal aufgeräumt, die UDF wurde eigentlich hier geboren: Link, da ist sogar schon die vielsagende Variablenbenennung ($a_, $c_, etc) vorhanden), steinigt mich nicht für den unleserlichen nicht wartbaren erroranfälligen Code. Den schreibe ich auch heute noch :D

    AutoIt
    #include-once
    
    ; #INDEX# =======================================================================================================================
    ; Title .........: DecToBin
    ; AutoIt Version : 3.3.12.0
    ; Date ..........: 01.05.2014
    ; Modified ......: 08.05.2023 (3.3.16.1)
    ;                  - [Added] _BinToDecA
    ;                  - [Added] _DecToBinA
    ;                  - [Added] _DecToBinPrefixTable
    ;                  - [Added] __AHE_BuildTreeFromSymbolHistogram & __AHE_TreeToLookupRec
    ;                           (falls Namenskollision auftritt, Huffman.au3 hat Vorrang, das hier ist nur eine Kopie)
    ; Modified ......: 12.05.2023
    ;                  - [Changed] _BinToDecA & _DecToBinA verwenden den Default Prefix Table, wenn der 2te Parameter 0 ist.
    ;                  - [Changed] _DecToBin hat jetzt einen Längenparameter als 2tes
    ;                  - [Rename] $D2BA, $D2BB, $D2BC umbenannt zwecks vermeidung von Namenskollisionen
    ; Language ......: Deutsch
    ; Description ...: Funktionen um zwischen Dezimal und Binärzahlen umzurechnen
    ; Author(s) .....: Mars
    ; ===============================================================================================================================
    
    ; #CURRENT# =====================================================================================================================
    ; _BinCap8
    ; _BinToDec
    ; _BinToDecA
    ; _DecToBin
    ; _DecToBinA
    ; _DecToBinPrefixTable
    ; __DecToBinStartup
    ; ===============================================================================================================================
    
    Global $D2BA[256], $D2BB[256], $D2BC[11111112]
    Global Const $D2B_DPT = _DecToBinPrefixTable() ; Default Prefix Table
    
    __DecToBinStartup()
    
    If @ScriptName = 'DecToBin.au3' Then __DecToBinExample()
    
    Func __DecToBinExample()
        ; Beispiel für adaptive Version.
        Local $bOnlyResults = False
    
        ; Generiere Liste aus Zufallszahlen
        Local $aNumbers[10]
        For $i = 0 To UBound($aNumbers) - 1 Step 1
            $aNumbers[$i] = Round(2^Random(0, 31-1, 1) * Random(0, 1)) ; Produziere Zufallszahlen mit sehr großen Unterschieden in der Länge.
        Next
    
        ; Nimm die Default Wahrscheinlichkeiten
        Local $iSumBits = 0, $iCount = 0
    
        ConsoleWrite('Eine Runde mit default Settings' & @CRLF)
        If Not $bOnlyResults Then ConsoleWrite('            Zahl   Bitrate  Encoded                                Used Bits Decoded' & @CRLF)
        For $i = 0 To UBound($aNumbers) - 1 Step 1
            Local $iNumber = $aNumbers[$i]
            Local $iBitrate = Ceiling(Log($iNumber+1+($iNumber=0?1:0))/Log(2))
            Local $sEncoded = _DecToBinA($iNumber)
            Local $iDecoded = _BinToDecA($sEncoded)
            Local $iBinaryLen = @extended
            Local $bError = $iNumber <> $iDecoded Or $iBinaryLen <> StringLen($sEncoded)
            If Not $bOnlyResults Then
                ConsoleWrite($bError ? '!' : ' ')
                ConsoleWrite(StringRight('               ' & $iNumber, 15) & ' (bits: '& StringRight(' ' & $iBitrate, 2) &') ')
                ConsoleWrite(StringLeft($sEncoded & '                                             ', 45) & ' ' & StringRight(' ' & $iBinaryLen, 2))
                ConsoleWrite(' ' & $iDecoded & @CRLF)
            EndIf
            $iSumBits += $iBinaryLen
        Next
        ConsoleWrite('Anzahl: ' & StringLeft(UBound($aNumbers) & '     ', 6) & _
        ' Bits: ' & StringLeft($iSumBits & '      ', 7) & _
        ' Bit/Number: ' & StringFormat('% 5.2f', $iSumBits / UBound($aNumbers)) & @CRLF)
    
        ; Nimm angepasste Wahrscheinlichkeiten
        ; Nicht gesetzte Werte werden als 0 interpretiert (haben also "kein Gewicht" bei der Baumbildung)
        ; sie werden aber dennoch berücksichtigt. Es ist also möglich auch Zahlen zu kodieren die aus
        ; bereichen kommen die mit 0 markiert sind. Das wird dann nur beliebig ineffizient.
        Local $aPropabilities[31]
        For $i = 0 To UBound($aNumbers) - 1 Step 1
            Local $iNumber = $aNumbers[$i]
            Local $iBitrate = Ceiling(Log($iNumber+1+($iNumber=0?1:0))/Log(2))
            $aPropabilities[$iBitrate-1] += 1
        Next
    ;~     _ArrayDisplay($aPropabilities, 'Custom Propabilities') ; muss nicht normiert werden.
        Local $aLUT = _DecToBinPrefixTable($aPropabilities), $iSumBits = 0, $iCount = 0
    ;~     _ArrayDisplay($aLUT, 'Lookup')
    
        ConsoleWrite(@CRLF & 'Eine runde mit eigener Wahrscheinlichkeitstabelle' & @CRLF)
        If Not $bOnlyResults Then ConsoleWrite('            Zahl   Bitrate  Encoded                                Used Bits Decoded' & @CRLF)
        For $i = 0 To UBound($aNumbers) - 1 Step 1
            Local $iNumber = $aNumbers[$i]
            Local $iBitrate = Ceiling(Log($iNumber+1+($iNumber=0?1:0))/Log(2))
            Local $sEncoded = _DecToBinA($iNumber, $aLUT)
            Local $iDecoded = _BinToDecA($sEncoded, $aLUT)
            Local $iBinaryLen = @extended
            Local $bError = $iNumber <> $iDecoded Or $iBinaryLen <> StringLen($sEncoded)
            If Not $bOnlyResults Then
                ConsoleWrite($bError ? '!' : ' ')
                ConsoleWrite(StringRight('               ' & $iNumber, 15) & ' (bits: '& StringRight(' ' & $iBitrate, 2) &') ')
                ConsoleWrite(StringLeft($sEncoded & '                                             ', 45) & ' ' & StringRight(' ' & $iBinaryLen, 2))
                ConsoleWrite(' ' & $iDecoded & @CRLF)
            EndIf
            $iSumBits += $iBinaryLen
        Next
        ConsoleWrite('Anzahl: ' & StringLeft(UBound($aNumbers) & '     ', 6) & _
        ' Bits: ' & StringLeft($iSumBits & '      ', 7) & _
        ' Bit/Number: ' & StringFormat('% 5.2f', $iSumBits / UBound($aNumbers)) & @CRLF)
    
    EndFunc
    
    
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Erzeugt einen Lookup Table zum enkodieren/dekodieren aus einer Wahrscheinlichkeitsliste.
    ;                  Aufbau:
    ;                  $aP[0]  = Wahrscheinlichkeit, dass eine Zahl die Länge  1 Bit hat
    ;                  $aP[1]  =                                               2
    ;                  $aP[n]  =                                               n
    ;                  $aP[30] =                                              31
    ;                  Da der Maximalwert des Enkoders/Dekoders uint31-1 ist, ist $aP grundsätzlich 31 Einträge groß (Array[31])
    ; ===============================================================================================================================
    Func _DecToBinPrefixTable($aP = 0)
        ; $aP[31] <- mehr als 31Bit geht nicht. Enthält die Wahrscheinlichkeiten für jede Bitrate.
        If Not IsArray($aP) Then
            Local $_[31]
            For $i = 0 To UBound($_) - 1 Step 1
                $_[$i] = 1 / 1.05^$i ; Initiale Wahrscheinlichkeiten je Bitrate. Leicht exponentiell, fast gleichverteilt.
            Next
            $aP = $_
        EndIf
        ; Normalisieren, falls es im Input vergessen wurde
        Local $s = 0
        For $i = 0 To UBound($aP) - 1 Step 1
            $s += $aP[$i]
        Next
        For $i = 0 To UBound($aP) - 1 Step 1
            $aP[$i] /= $s
        Next
        Local $HT[UBound($aP) * 2][3], $L1D[UBound($aP)], $L2D[UBound($aP)][2]
        __AHE_BuildTreeFromSymbolHistogram($aP, $HT) ; geklaut von Adaptive Huffman Encoder
        __AHE_TreeToLookupRec($L1D, $HT) ; geklaut von Adaptive Huffman Encoder
        For $i = 0 To UBound($L1D) - 1 Step 1
            $L2D[$i][0] = StringLen($L1D[$i]) ; Die Länge schonmal speichern
            $L2D[$i][1] = $L1D[$i]
        Next
        Return $L2D
    EndFunc
    
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Adaptives enkodieren von Integern (bis uint31 - 1) via Prefix Tabelle.
    ;                  In $aLUT ist ein eindeutiger Lookup Table für die Prefixes. Diesen kann man z.B. via
    ;                  Huffman generieren.
    ; ===============================================================================================================================
    Func _DecToBinA($d, $aLUT = 0)
        If Not IsArray($aLUT) Then $aLUT = $D2B_DPT
        Local $iBits = Ceiling(Log($d+1+($d=0?1:0))/Log(2))
        If $iBits = 1 Then
            Return $aLUT[$iBits - 1][1] & _DecToBin($d, $iBits)
        Else
            Return $aLUT[$iBits - 1][1] & StringTrimLeft(_DecToBin($d, $iBits), 1)
            ; Wir wisseen: hier steht IMMER eine '1', also kann die 1 weg.
            ; Begründung: Da wir die Zahlen je nach Bitrate kodieren würde die
            ;             Bitrate um 1 sinken, wenn vorne eine '0' stehen würde,
            ;             also ist hier immer eine '1'. Ausnahme ist der Fall
            ;             für ein einziges Bit was '0' oder '1' sein kann und für
            ;             die Zahlen 0 oder 1 steht.
        EndIf
    EndFunc
    
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Adaptives dekodieren von Links. In @extended ist die Länge der dekodierten Zahl in Bin.
    ;                  In $aLUT ist ein eindeutiger Lookup Table für die Prefixes. Diesen kann man z.B. via
    ;                  Huffman generieren.
    ; ===============================================================================================================================
    Func _BinToDecA($b, $aLUT = 0)
            If Not IsArray($aLUT) Then $aLUT = $D2B_DPT
        For $iBits = 1 To 30 Step 1 ; Könnte man über partial match tree lösen. Hab aber keine Lust. Daher linear durchprobieren.
            If StringLeft($b, $aLUT[$iBits - 1][0]) = $aLUT[$iBits - 1][1] Then
                If $iBits = 1 Then
                    Return SetExtended($iBits + $aLUT[$iBits - 1][0], _BinToDec(StringMid($b, $aLUT[$iBits - 1][0] + 1, $iBits)))
                Else
                    Return SetExtended($iBits + $aLUT[$iBits - 1][0] - 1, _BinToDec(('1' & StringMid($b, $aLUT[$iBits - 1][0] + 1, $iBits - 1))))
                EndIf
            EndIf
        Next
        Return SetError(1, 0, "ERROR: Verwendeter Prefix Lookuptable passt nicht zur eingegebenen Binärzahl.")
    EndFunc
    
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: False: Verlängert eine Binärzahl zur Umrechnung ins B256 System | True: Entfernt die Verlängerung
    ; ===============================================================================================================================
    Func _BinCap8($sBin, $bUnCap = False)
        Local Static $aLeft[8] = ['00000000', '0000001', '000001', '00001', '0001', '001', '01', '1']
        If Not $bUnCap Then Return $aLeft[Mod(StringLen($sBin), 8)] & $sBin
        For $i = 0 To 7 Step 1
            If StringLeft($sBin, StringLen($aLeft[$i])) = $aLeft[$i] Then Return StringTrimLeft($sBin, StringLen($aLeft[$i]))
        Next
    EndFunc   ;==>_BinCap8
    
    ; --------------------------------------------------------|
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Wandelt eine Dualzahl(String) in eine Dezimalzahl um
    ; ===============================================================================================================================
    Func _BinToDec($s)
        Local $l = StringLen($s)
        Return $l < 9 ? $D2BC[$s] : $l < 17 ? $D2BC[StringTrimRight($s, 8)] * 256 + $D2BC[StringRight($s, 8)] : $l < 25 ? _
        $D2BC[StringTrimRight($s, 16)] * 65536 + $D2BC[StringRight(StringTrimRight($s, 8), 8)] * 256 + $D2BC[StringRight( _
        $s, 8)] : BitShift($D2BC[StringTrimRight($s, 24)], -24) + $D2BC[StringRight(StringTrimRight($s, 16), 8)] * 65536 _
        + $D2BC[StringRight(StringTrimRight($s, 8), 8)] * 256 + $D2BC[StringRight($s, 8)]
    EndFunc   ;==>_BinToDec
    
    ; #FUNCTION# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Ermittelt eine Dualzahl(String) aus einer Dezimalzahl die kleiner als 2^31 ist
    ; ===============================================================================================================================
    Func _DecToBin($d, $l)
        Return StringRight('00000000000000000000000000000000' & ($d < 256 ? $D2BA[$d] : $d < 65536 ? $D2BA[$d / 256] & $D2BB[BitAND($d, 255)] _
        : $d < 16777216 ? $D2BA[$d / 65536] & $D2BB[BitAND($d / 256, 255)] & $D2BB[BitAND($d, 255)] : $D2BA[BitShift($d, 24)] & $D2BB[BitAND($d / _
        65536, 255)] & $D2BB[BitAND($d / 256, 255)] & $D2BB[BitAND($d, 255)]), $l)
    EndFunc   ;==>_DecToBin
    
    ; #INTERNAL# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Initialisiert die DecToBin UDF
    ; ===============================================================================================================================
    Func __DecToBinStartup()
        Local Static $bReady = False
        If $bReady Then Return
        Local $t = DllStructCreate('char[64]'), $p = _
                DllStructGetPtr($t), $hDll = DllOpen('msvcrt.dll')
        For $i = 0 To 255 Step 1
            DllCall($hDll, 'ptr:cdecl', '_i64toa', 'int64', _
                    $i, 'ptr', $p, 'int', 2)
            $D2BA[$i] = DllStructGetData($t, 1)
            $D2BB[$i] = StringRight('0000000' & $D2BA[$i], 8)
            $D2BC[$D2BA[$i]] = $i
        Next
        DllClose($hDll)
        $bReady = True
    EndFunc   ;==>_DecToBinStartup
    
    ; #INTERNAL# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Geklaut von mir selbst. (Adaptive Huffman Encoder)
    ; ===============================================================================================================================
    Func __AHE_TreeToLookupRec(ByRef $aLookup, ByRef $__AHET, $i = 0, $sPath = '')
        If $__AHET[$i][2] = '' Then
            $aLookup[$__AHET[$i][0]] = $sPath
        Else
            __AHE_TreeToLookupRec($aLookup, $__AHET, $__AHET[$i][0], $sPath & '0')
            __AHE_TreeToLookupRec($aLookup, $__AHET, $__AHET[$i][2], $sPath & '1')
        EndIf
    EndFunc   ;==>__AHE_TreeToLookupRec
    
    ; #INTERNAL# ====================================================================================================================
    ; Author ........: Mars
    ; Description ...: Geklaut von mir selbst. (Adaptive Huffman Encoder) Vermutlich die beste Funktion die ich je geschrieben habe.
    ; ===============================================================================================================================
    Func __AHE_BuildTreeFromSymbolHistogram(ByRef $aSymHist, ByRef $__AHET)
    
        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
    
        Local $__AHEE = UBound($aSymHist)  ;         | 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 UBound($aSymHist) - 2 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   ;==>__AHE_BuildTreeFromSymbolHistogram
    Alles anzeigen

    Edit 10.05.23: Vollständig adaptive Version hinzugefügt die bis uint31-1 funktioniert (und nicht wie vorher bis uint28-1)

    Funktionsweise: Eine Integerzahl wird als "Prefix" + "Bitrepräsentation" abgebildet.

    Beispiel:

    Zahl = 244368

    Theoretisch benötigte Bits = 18 (da 2^18-1 = 262143 >= Zahl), normalerweise speichert man aber 32 Bit. Und das wollen wir optimieren.

    Binärdarstellung: 1 & 11011101010010000 Erstes Bit kann entfernt werden, denn es ist immer eine Eins, außer bei den Zahlen 0 und 1, wo dieses Bit tatsächlich gebraucht wird.

    Prefix: 00111 (Beispielhaft, ergibt sich aus HuffmanTree)

    Resultat: 00111 & 11011101010010000 -> 22 Bits um eine 18 Bit Zahl zu kodieren.

    - Außerdem kann man eine eigene Wahrscheinlichkeitstabelle angeben in der man festlegen kann wie wahrscheinlich Zahlen in gewissen Bereichen sind um noch ein Paar Bits einzusparen. Diese Tabelle muss man allerdings beim Dekodieren ebenfalls mitliefern. Ansonsten benutzt man einfach die "default" Tabelle (die ich von Hand gebastelt habe, die ist ganz okay für die Meisten Fälle).

    - Der Prefix wird nicht mehr (wie vorher) von Hand eingetackert, sondern vollautomatisch (Huffman) generiert.

    - Beim Dekodieren wird die Bitlänge mit ausgegeben (siehe @extended), es sind also keine Trennzeichen zwischen aufeinanderfolgenden Zahlen nötig, man kann die Bits einfach hintereinanderschreiben.

    Hinweis: Die Adaptive Version bringt natürlich nur etwas, wenn die Zahlen die man kodieren will nicht gleichverteilt sind. Egal wie cool die Funktion ist, die Entropie kann sie nicht überlisten.


    Anwendungsfall: (hypothetisch) Ich möchte ganz viele Zahlen die maximal uint31 groß sind möglichst gut verpackt speichern. Die Zahlen sind nicht gleichverteilt (sie haben irgendein Muster, z.B. kleine Zahlen sind sehr häufig, Zahlen im bereich 2000 sind auch sehr häufig (z.B. für Jahreszahlen), große Zahlen wie 25095382 sind relativ selten), aber es sind so viele verschiedene, dass eine Entropiekodierung nicht funktioniert (da werden ja "zahlen" als einzelne Symbole interpretiert, und wenn alle Zahlen unterschiedlich sind wird die Tabelle die man speichern muss größer als wenn man die Zahlen direkt mit 31Bit/Zahl speichert). Die hier gezeigte Methode verwendet eine Entropiekodierung auf "Bereiche" anstatt auf einzelne Zahlen. Deshalb ist das ganze quasi ein "Pseudo Huffman für Zahlen die nicht mehrfach auftauchen aber in einer ähnlichen Größenordnung liegen".

    Edit 12.05.23: Paar kleine Änderungen in der UDF für mehr Benutzerfreundlichkeit.

    Falls Fehler auftauchen: Meldet euch, ich habe das nur kurz getestet.

    lg

    M

  • [Gelöst] GDIPlus Image hat falsche Größe

    • Mars
    • 25. April 2023 um 19:49

    Mich hat das neulich vollkommen auf die Palme gebracht (und ich dachte ich bin komplett verblödet :rofl: )

    Habe ein Bild via _GDIPlus_GraphicsDrawImage angezeigt und anschließend mit der Maus ein Rechteck darauf markiert das dann ausgeschnitten werden sollte, und das hatte jedes Mal ein paar Pixel falsch (da der Unterschied von 96 DPI auf 100 DPI so klein ist habe ich gedacht irgendwo muss es seltsame Rundungsfehler geben). Es hat Stunden (und 2-3 Nächte darüber Schlafen, als ich das Skript schon als "fertig, klappt aber nicht" abgelegt hatte) gebraucht bis mir ein Licht aufgegangen ist^^

    lg

    M

  • [Gelöst] GDIPlus Image hat falsche Größe

    • Mars
    • 24. April 2023 um 22:19

    Moin,

    das Problem ist bereits gelöst (bzw. ein einfacher Workaround gefunden), weil mich die Sache aber lange geplagt hat schreibe ich hier mal um was es geht, falls andere das selbe Problem haben.

    Je nachdem mit welchem Programm man Bilder bearbeitet wird im Bild ein unterschiedlicher DPI Wert gesetzt. Manche Programme denken 72 ist gut, manche 96, manche 100, und manche nehmen den Wert den dein Bildschirm gerade eingestellt hat. In vielen Fällen ist einem der DPI Wert aber vollkommen egal, alles was man will ist "ein Pixel = ein Pixel", no questions asked.

    Im Beispiel ist 2x dasselbe Bild (1x mit "default Einstellungen" meines Programms = 100 DPI), und 1x "ohne" explizite angabe der DPI (dann nimmt mein PC automatisch 96, wie das bei anderen Leuten aussieht weiß ich nicht), und ein Skript das die Bilder via _GDIPlus_GraphicsDrawImage anzeigt. Man sieht, die Bilder sind verschieden groß, und gerade bei Pixeligen Sachen entstehen subsampling Artefakte. Das Problem lässt sich lösen, indem man _GDIPlus_BitmapSetResolution verwendet und allen Bildern denselben Wert verpasst, oder explizit die Größe beim Zeichnen via _GDIPlus_GraphicsDrawImageRect mitgibt.

    Fazit: _GDIPlus_GraphicsDrawImage berücksichtigt beim Zeichnen die DPI und verursacht damit manchmal ungewünschte Probleme (z.B Bilder haben die falsche Größe).

    Edit: Ja, ich habe auf beide Testbilder "Testbild 1" geschrieben... Eigentlich wollte ich "Testbild 2" auf das 2te Bild schreiben, dann ist mir aber eingefallen, dass es sich dann ja gar nicht mehr um "das selbe" Bild handelt, und ich wollte ja "das selbe" Bild nur mit verschiedenen DPI Werten haben... Zwickmühle :D

    lg

    M

    Dateien

    Example_GDIPlusImageWrongSize.zip 12,79 kB – 340 Downloads
  • Endlosschleife funktioniert nicht mehr ab gewisser Zeit

    • Mars
    • 11. April 2023 um 22:19

    Ich kann nur raten was hier passiert... Hast du die Rückgabewerte und @errors von ProcessExists (hat kein @error) und RunWait (hat @error) mal abgefragt? Es wäre wichtig zu wissen an welcher Stelle das Problem auftritt.

    Außerdem würde ich erstmal ein While Sleep(100) aus dem While 1 machen, Computer sind auch nur Menschen, und wenn man dich 10.000x pro Sekunde fragt ob ein Prozess existiert geht dir das nach 20 Minuten vielleicht einfach auf den Zünder und du antwortest nicht mehr ^^

    M

  • Schreiben in ein Array in einer Map

    • Mars
    • 24. März 2023 um 10:41

    Genau das selbe hatte ich auch (bei mir waren es Vertices = Array[double] in einer Geometry = Map[Vertices] in einer Liste = Array[Geometry]). Man bekommt mit der Klammernotation nur Lesezugriff, wenn man etwas schreiben will führt kein Weg an einer Wrapperfunktion (die nur dafür da ist "ByRef" verwenden zu können) vorbei.

    Wenn man überall Maps verwendet (und Arrays komplett durch Maps ausdrückt) klappt es, wobei ich keine Performancetests von "2d, 3d, Nd, verschachtelte Map vs 2d, 3d, Nd ByRef" gemacht habe. Für große Maps ist das vermutlich sehr langsam (das hatten wir mal ausprobiert. "große" Maps (1000+ elemente, ich weiß die genaue Zahl nicht mehr) werden extrem langsam), und für kleine wird es keinen großen Unterschied machen.

    AutoIt
    Global $aA[], $mM[]
    
    $aA[0] = 1111
    $mM[1] = $aA
    $aA = Null
    
    ConsoleWrite("> " & $mM[1][0] & @CRLF)
    
    $mM[1][0] = 2222
    
    ConsoleWrite("> " & $mM[1][0] & @CRLF)
    Alles anzeigen

    M

  • Farben Sortieren / Gruppieren

    • Mars
    • 15. März 2023 um 15:46

    Sooo dann schmeiß ich auch mal meinen Hut in die Runde.

    -> Idee war: Sortiere zunächst alles heraus was nach "Graustufen" aussieht und sortiere den Rest. Dadurch hat man etwas weniger "schwarze und weiße Linien" im Regenbogen. Wirklich gut sieht das auch nicht aus, aber vielleicht inspiriert die Idee ja irgendwen :)

    AutoIt
    Func SortByHSL2(ByRef $aColortable)
        Local $aColortable2[UBound($aColortable)][9]
        Local $a, $i, $hsl_
        For $i = 0 To UBound($aColortable) - 1
            $a = _RGB2LAB($aColortable[$i])
            $hsl_ = RGB2HSL($aColortable[$i])
            $aColortable2[$i][0] = $aColortable[$i]
            $aColortable2[$i][1] = $a[0] ; LAB -> L
            $aColortable2[$i][2] = Sqrt($a[1]^2 + $a[2]^2) ; chroma
            $aColortable2[$i][3] = Abs($a[0] - 50) ; L umformen um "hell und dunkel" rauszufiltern
            $aColortable2[$i][4] = $hsl_[0] ; HSL -> H (könnte man via Farbwinkel aus LAB auch machen, hab ich ausprobiert, sah nicht so schön aus)
        Next
        Local $10 = Int(UBound($aColortable)/10)
        _ArraySort($aColortable2, 0, 0, 0, 2) ; chroma -> ziemlich "unbunte" farben herausfiltern (10%)
        _ArraySort($aColortable2, 1, 1 * $10 + 1, 0 * $10, 3) ; abs(L-50) -> sehr helle und sehr dunkle Farben herausfiltern
        _ArraySort($aColortable2, 0, 1 * $10 + 1, 5 * $10, 2) ; chroma -> von den hellen und dunklen Farben die unbuntesten raussuchen (nochmal 10%)
        _ArraySort($aColortable2, 0, 0 * $10 + 0, 2 * $10, 1) ; Die packt man links an das erste 5tel als eine Art "Pseudograustufenliste" (darin sind 20% aller Farben)
        _ArraySort($aColortable2, 0, 2 * $10 + 1, 0 * $10, 1) ; L -> sortiere nach Helligkeit
        _ArraySort($aColortable2, 0, 2 * $10 + 1, 6 * $10, 4) ; H -> Sortiere nach Hue (1x für niedrige Helligkeit)
        _ArraySort($aColortable2, 1, 6 * $10 + 1, 0 * $10, 4) ; H -> Sortiere nach Hue (1x für hohe Helligkeit)
        For $i = 0 To UBound($aColortable2) - 1
            $aColortable[$i] = $aColortable2[$i][0]
        Next
        Dim $aColortable2[0]
    EndFunc
    Alles anzeigen

    unnamed.png

    M

  • Umfrage zum Thema "Wie informiert Ihr Eure User in einer Domain am PC-Arbeitsplatz über umgehend wichtige und zu beachtende Dinge?"

    • Mars
    • 15. März 2023 um 00:24

    Bei uns wird alles über E-Mails geregelt, auch kurzfristige Informationen (zum Glück bin ich nicht wichtig genug, sodass ich nur 5 Mails am Tag bekomme und nicht 100^^). Aber tatsächlich: "Druckerausfall", "Server Neustart", "Wartung", "andere Probleme" gibts eigentlich häufiger (da kommen so 1 bis 3 Meldungen pro Woche, wird ja vorsortiert, dass ich nur die Sachen bekomme die für mich auch relevant sind). 90% davon tangieren mich aber aktuell trotzdem nicht, da ich im Homeoffice sitze und mir ein PC gegeben wurde (privat PC's sind bei uns auch verboten), an dem ich (fast) alles machen kann. Von daher: "Nein, brauche ich gerade nicht, aber wäre ggf. irgendwann mal interessant", ich weiß ja nicht wo ich in 10 Jahren lande^^

    M

  • Map: Value Funktionspointer nicht per Punktnotation nutzbar

    • Mars
    • 9. März 2023 um 13:09

    Das erinnert mich daran wie die Leute aus dem EN-Forum unbedingt und unter jeder Bedingung wollen, dass wir Maps nicht als "Fake-Objekte" missbrauchen (obwohl das eine komplett valide Anwendungsweise ist).

    AutoIt
    Global $self
    
    Global $FakeObjekt[]
    $FakeObjekt.position = Array(10, 20)
    $FakeObjekt.printLen = _printLen
    Func _printLen()
        Local $l = Sqrt($self.position[0]^2 + $self.position[1]^2)
        ConsoleWrite($l & @CRLF)
    EndFunc
    
    ;~ _($FakeObjekt).printLen() ; geht nicht
    (_($FakeObjekt).printLen)() ; geht
    
    
    Func _(ByRef $m)
        $self = $m
        Return $m
    EndFunc
    
    Func Array($a, $b)
        Local $c = [$a, $b]
        Return $c
    EndFunc
    Alles anzeigen

    (Wahrscheinlich wird mein "same scope byref" feature request abgelehnt. Das würde den ganzen "Fake-Objekt" Kram sogar (fast) ohne Overhead und mit Schreibzugriff ermöglichen, da man $self = byref $m schreiben könnte, sodass $self echten Schreibzugriff hat und gleichzeitig muss $m nicht kopiert werden (da es byref ist, allerdings müsste dann auch Return ByRef $m möglich sein um den Overhead zu reduzieren)).


    Das obige Skript hat nur Lesezugriff via $self (logisch... es ist ja auch nur eine Kopie)

    lg

    M

  • GUI mit benutzerdefinierter Titelleiste

    • Mars
    • 23. Februar 2023 um 19:56

    Mir sind ein paar Kleinigkeiten aufgefallen die ich vermutlich irgendwo eingebaut hätte:

    - Kleiner Hinweis wie du die Events nicht andauernd via Adlib durchlaufen musst: Verwende GUIOnEventMode und registriere dir GUI_EVENT_MOUSEMOVE. Dann wird die Funktion nur aufgerufen, wenn die Maus bewegt wird. Dadurch wird dein Programm nebenbei auch sehr viel reaktiver, weil nicht "alle 100ms" geprüft wird, sondern "sobald sich die Maus einen Pixel bewegt". Gleichzeitig wird keine Rechenleistung verbraucht wenn die Maus stillsteht.

    - Noch eine Idee wäre WM_NCHITTEST & Return $HTCAPTION (klappt nur, wenn die Maus "nicht" über einem Ctrl mit einem eigenen Handle ist, z.B. für GDI+ Stuff). Damit kann man ein Fenster bewegen, wenn man auf den Hintergrund des Fensters (und nicht auf ein Ctrl) klickt. Bin gerade nicht sicher ob, und wie das sinnvoll ist, aber vielleicht bringt die die Info ja etwas :) (PS: NCHITTEST feuert 1x pro Frame, also alle 16.6ms. Wenn man es nicht braucht sollte man es also vllt doch lieber weglassen^^)

    - GUIGetCursorInfo trägt bereits informationen zum Ctrl in [4], da braucht man nicht mehr umständlich via Positionen zu berechnen wo die Maus ist.

    - Bei Ctrls Farben zu aktualisieren tendiert zu flackern (auch wenn man es hier jetzt nicht wirklich sieht). Versuche die aktuellen Daten (Farbe, Schriftfarbe, Symbol, etc) nur dann zu aktualisieren wenn sich etwas ändert.

    Anbei ein Minimalbeispiel wie man ein Fenster bewegt und ein Ctrl umfärbt. Das Beispiel verwendet "alles" oben angesprochene, ob es sinnvoll ist UND nicht :D

    AutoIt
    #include <WindowsConstants.au3>
    #Include <GUIConstantsEx.au3>
    
    Opt('GUIOnEventMode', 1)
    
    
    Global $hGUI = GUICreate('Testfenster', 500, 500, -1, -1, $WS_POPUPWINDOW)
    Global $hLAB = GUICtrlCreateLabel('', 100, 100, 100, 100, -1, $GUI_WS_EX_PARENTDRAG)
    GUICtrlSetBkColor($hLAB, 0x808080)
    GUISetState(@SW_SHOW)
    
    GUISetOnEvent(-3, Xit)
    GUISetOnEvent($GUI_EVENT_MOUSEMOVE, GUI_EVENT_MOUSEMOVE)
    GUIRegisterMsg($WM_NCHITTEST, WM_NCHITTEST)
    
    Func Xit()
        Exit
    EndFunc
    
    While Sleep(10)
    WEnd
    
    Func WM_NCHITTEST($hWnd, $iMsg, $wParam, $lParam)
        ; Feuert nur, wenn man "über dem aktuellen Fenster ist". Ctrls zählen nicht dazu.
        ToolTip('x: ' & BitAND($lParam, 0xFFFF) & @CRLF & 'y: ' & BitAND(BitShift($lParam, 16), 0xFFFF))
        Return $HTCAPTION ; Fenster festhalten, wenn man klickt.
    EndFunc
    
    Func GUI_EVENT_MOUSEMOVE()
        Local $aInfo = GUIGetCursorInfo() ; Label mit gepufferter Farbe ohne Adlib umfärben wenn die Maus darüber ist.
        Local Static $iLastColor = 0x808080
        If $aInfo[4] = $hLAB Then
            If $iLastColor <> 0xA0A0A0 Then
                $iLastColor = 0xA0A0A0
                GUICtrlSetBkColor($hLAB, 0xA0A0A0)
            EndIf
        Else
            If $iLastColor <> 0x808080 Then
                $iLastColor = 0x808080
                GUICtrlSetBkColor($hLAB, 0x808080)
            EndIf
        EndIf
    EndFunc
    Alles anzeigen

    Edit: Es gibt auch noch eine Menge andere WM_XXX die man gebrauchen könnte. Am besten mal alle durchlesen (sind leider ziemlich viele^^).

    Edit2: https://www.autoitscript.com/wiki/Moving_an…zing_PopUp_GUIs <- Pflichtlektüre 8)

    lg

    M

  • [GDI+] Maussteuerung UDF

    • Mars
    • 16. Februar 2023 um 17:46

    Probier das hier mal aus. Ist es das was du meinst?

    Mausinfo bekommt man jetzt per $Transform.Mouse, WorldSpace Koordinaten bekommt man via _GDIPlus_TransformMouseGetPos($Transform). Außerdem (weil es eh berechnet wird) gibts in $Transform.containsMouse noch die Info ob die Maus gerade im Rechteck ist. Vermutlich kann man das noch in $Transform.Mouse.inside oder ähnliches verschieben, ich bin aber kein Meister der Namensgebung, daher keine Ahnung.

    Einstellungen die Hinzugekommen sind:

    - Zoom Begrenzung (Min und Max)

    - Translation Begrenzung (via BorderX und BorderY implementiert)

    Ich habe mich dafür entschieden $Transform.einstellung, oder $Transform.information zu verwenden anstatt jede einzelne Sache in eine Funktion zu wrappen. Es ist meines Erachtens nach dumm 10 Funktionen zu schreiben, wenn man die Werte sowieso direkt setzen kann. Wenn man wissen will was alles einstellbar ist muss man eben in _GDIPlus_TransformCreate nachlesen was es alles gibt und was es alles macht.

    Neues Beispielskript das Zeigt was dazugekommen ist. Für die WorldSpace Koordinaten sind extra ein paar Testpixel gesetzt die man sich reingezoomt ansehen kann um zu schauen wie die Koordinaten aussehen.

    Edit1: Startpost geupdated.

    Edit2: Code entfernt, im Startpost ist der "richtige" Code.

    lg

    M

  • [GDI+] Maussteuerung UDF

    • Mars
    • 16. Februar 2023 um 03:45

    Moin,

    Mir ist es jetzt schon häufiger untergekommen, dass ich in einem GDI+ Fenster gerne mit der Maus etwas bewegen und ggf. zoomen möchte (Linksklick -> Drag, Mausrad -> Zoom). Jedes Mal habe ich es wieder von neuem programmiert und mich geärgert, dass immer irgendwelche Zahlen nicht gestimmt haben (z.B. bleibt der Punkt unter der Maus beim Zoomen nicht an derselben Stelle, usw). Daher gibts jetzt eine UDF dazu die hoffentlich jedem weiterhilft der dasselbe Problem hat und ein wenig "interaktivere" GDI+ Anwendungen schreiben will. Da ist es nämlich immer schön, wenn der User ein wenig Spaß haben kann und nicht alles so furchtbar statisch ist.

    Es ist eine sehr kurze (ca. 100 Zeilen [Edit: jetzt 140 [Edit2: jetzt 160]]) UDF geworden. Verbesserungsvorschläge / Korrekturen sind gerne gesehen.

    Hier noch ein Minimalbeispiel, damit man schauen kann was die UDF eigentlich macht, und wie die Anwendung ist.

    Es sind nur 3 Zeilen nötig um einem GDI+ Viewport eine Maussteuerung zu verpassen. Einfacher habe ich es nicht hinbekommen ^^

    Für Einstellungen muss man in _GDIPlus_TransformCreate nachsehen welche Variablen es gibt, in den Kommentaren steht wofür sie verwendet werden.

    AutoIt
    #include '_GDIPlus_Transform.au3'
    ; Beispiel für ein simples GDI+ Fenster mit Maussteuerung
    
    _GDIPlus_Startup()
    
    Global Const $iW = 800, $iH = 500
    
    Global Const $Rect1 = [10, 10, $iW / 2 - 20, $iH - 20]
    Global Const $Rect2 = [$iW/2 + 10, 10, $iW / 2 - 20, $iH - 20]
    
    Global $hGUI = GUICreate('Testfenster', $iW, $iH)
    Global $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    Global $hBMP1 = _GDIPlus_BitmapCreateFromGraphics($Rect1[2], $Rect1[3], $hGFX) ; Zwei unabhängige Zeichenflächen
    Global $hBMP2 = _GDIPlus_BitmapCreateFromGraphics($Rect2[2], $Rect2[3], $hGFX)
    Global $hBUF1 = _GDIPlus_ImageGetGraphicsContext($hBMP1)
    Global $hBUF2 = _GDIPlus_ImageGetGraphicsContext($hBMP2)
    Global $hBRU = _GDIPlus_BrushCreateSolid()
    _GDIPlus_GraphicsSetSmoothingMode($hBUF1, 2) ; Verschiedene Buffer. Der Linke bekommt smoothing
    
    Global $RandomObjects = 10, $iSelectedObject1 = -1, $iSelectedObject2 = -1
    Global $RandomStuff1[$RandomObjects]
    Global $RandomStuff2[$RandomObjects]
    
    For $i = 0 To $RandomObjects - 1 Step 1
        $RandomStuff1[$i] = RandomCircle()
        $RandomStuff2[$i] = RandomCircle()
    Next
    
    Global $hTransform1 = _GDIPlus_TransformCreate($hGUI, $hBUF1, $Rect1[0], $Rect1[1], $Rect1[2], $Rect1[3])
    Global $hTransform2 = _GDIPlus_TransformCreate($hGUI, $hBUF2, $Rect2[0], $Rect2[1], $Rect2[2], $Rect2[3])
    
    $hTransform1.zoomMin = 0.01   ; kann sehr weit rauszoomen
    $hTransform1.zoomMax = 100    ; und sehr weit reinzoomen (schau dir den Pixel bei 0/0 an. Im ToolTip sind die WorldSpace Koordinaten der Maus)
    $hTransform2.zoomMin = 1      ; kann nicht verkleinert werden
    $hTransform2.zoomMax = 2      ; nur faktor 2 vergrößerung erlaubt
    $hTransform2.zoomStep = 1.05  ; kleine Schrittweite
    $hTransform2.borderX = 100    ; man kann in X Richtung nicht außerhalb des ursprünglichen Rechtecks sein (WorldSpace Wert, keine "pixel")
    $hTransform2.borderY = 100    ; man kann in Y Richtung um ein halbes Feld außerhalb sein.
    $hTransform2.smoothZoom = 0   ; Deaktiviere smoothZoom
    $hTransform1.moveButton = $_GDIPT_MIDDLE
    
    GUISetState(@SW_SHOW, $hGUI)
    
    While GUIGetMsg() <> -3
    
        _GDIPlus_GraphicsClear($hBUF1, 0xFF202020)
        _GDIPlus_GraphicsClear($hBUF2, 0xFF404040)
    
        _GDIPlus_TransformBegin($hTransform1)
        Draw($hBUF1, $RandomStuff1, _GDIPlus_TransformMouseGetPos($hTransform1), $hTransform1.Mouse.leftDown, $iSelectedObject1)
        _GDIPlus_GraphicsFillRect($hBUF1, 0, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_GraphicsFillRect($hBUF1, 100, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_GraphicsFillRect($hBUF1, 0, 100, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_TransformEnd($hTransform1)
    
        _GDIPlus_TransformBegin($hTransform2)
        Draw($hBUF2, $RandomStuff2, _GDIPlus_TransformMouseGetPos($hTransform2), $hTransform1.Mouse.rightDown, $iSelectedObject2)
        _GDIPlus_GraphicsFillRect($hBUF2, 0, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_GraphicsFillRect($hBUF2, 100, 0, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_GraphicsFillRect($hBUF2, 0, 100, 1, 1, $hBRU) ; Testpixel zum anschauen
        _GDIPlus_TransformEnd($hTransform2)
    
        _GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP1, $Rect1[0], $Rect1[1], $Rect1[2], $Rect1[3])
        _GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP2, $Rect2[0], $Rect2[1], $Rect2[2], $Rect2[3])
    
    WEnd
    
    _GDIPlus_BrushDispose($hBRU)
    _GDIPlus_GraphicsDispose($hBUF2)
    _GDIPlus_GraphicsDispose($hBUF1)
    _GDIPlus_BitmapDispose($hBMP2)
    _GDIPlus_BitmapDispose($hBMP1)
    _GDIPlus_GraphicsDispose($hGFX)
    _GDIPlus_Shutdown()
    
    Func ToolTipPos(ByRef $hTransform)
        Local $a = _GDIPlus_TransformMouseGetPos($hTransform)
        ToolTip(StringFormat('x: % 6.2f\ny: % 6.2f', $a[0], $a[1]))
    EndFunc
    
    Func Draw($hGFX, ByRef $RandomStuff, $aPos, $bPressed, ByRef $iSelectedObject)
        _GDIPlus_BrushSetSolidColor($hBRU, 0x20FFFFFF)
        _GDIPlus_GraphicsFillRect($hGFX, 0, 0, $iW/2-20, $iH-20, $hBRU)
        For $i = 0 To UBound($RandomStuff) - 1 Step 1
            _GDIPlus_BrushSetSolidColor($hBRU, ($RandomStuff[$i])[3])
            _GDIPlus_GraphicsFillEllipse($hGFX, ($RandomStuff[$i])[0] - ($RandomStuff[$i])[2], ($RandomStuff[$i])[1] - ($RandomStuff[$i])[2], 2 * ($RandomStuff[$i])[2], 2 * ($RandomStuff[$i])[2], $hBRU)
            If $bPressed And ((($RandomStuff[$i])[0] - $aPos[0])^2+(($RandomStuff[$i])[1] - $aPos[1])^2)^0.5 < ($RandomStuff[$i])[2] Then $iSelectedObject = $i
        Next
        If Not $bPressed Then $iSelectedObject = -1
        If $iSelectedObject <> -1 Then
            Local $r = $RandomStuff[$iSelectedObject]
            $r[0] = $aPos[0]
            $r[1] = $aPos[1]
            $RandomStuff[$iSelectedObject] = $r
        EndIf
    EndFunc
    
    Func RandomCircle()
        Local $a = [Random(0, $iW/2 - 20), Random(0, $iH-20), Random(5, 50), Int('0xFF' & Hex(Random(0, 0xFFFFFF), 6))]
        Return $a
    EndFunc
    Alles anzeigen

    Edit 16.02.23:

    - Added: $Transform.Mouse [x, y, leftDown, rightDown, ctrlID]. Wird in TransformBegin automatisch aktualisiert und kann jederzeit abgerufen werden.

    - Added: $Transform.borderX & $Transform.borderY. Damit setzt man fest wie weit das Verschieben außerhalb des eigentlichen Bereichs gehen soll.

    - Added: $Transform.zoomMin & $Transform.zoomMax. Damit setzt man fest wie weit man hinein- bzw. herauszoomen kann.

    - Added: $Transform.smoothZoom. Damit bestimmt man wie "weich" der Zoom sein soll. Ein Wert von 0 deaktiviert das Feature. Erlaubt sind alle positiven reellen Zahlen.

    - Added: $Transform.containsMouse. Wird in TransformBegin automatisch gesetzt und gibt an ob die Maus im Viewport ist oder nicht.

    - Added: _GDIPlus_TransformMouseGetPos. Gibt die Koordinaten der Maus in Weltkoordinaten an. (im Beispielskript im Tooltip angezeigt. Schaut euch die Testpixel z.B. bei 0/0 an)

    Edit: 23.02.23:

    - Added: $Transform.moveButton. Hier kann man $_GDIPT_LEFT, $_GDIPT_RIGHT, $_GDIPT_MIDDLE angeben.

    - Added: $Transform.primaryDown. Hier kann man ablesen ob der bei moveButton gewählte Button gerade gedrückt ist.

    - Updated: Beispielskript, zur besseren Demonstration wozu man die Weltkoordinaten verwenden kann (z.B. um Objekte mit der Maus zu verschieben)

    - Beispiel, Links: Drag mit Mausradklick (middle), Objekte einzeln mit Linksklick auswählen und verschieben.

    - Beispie, Rechts: Drag mit Linksklick, Objekte mit Rechtsklick verschieben. (Soll demonstrieren, dass man auch interaktive Sachen innerhalb einer Trafo machen kann).

    lg

    M

    Dateien

    _GDIPlus_Transform.au3 8,01 kB – 388 Downloads
  • 3D mit GDI+ (A3D.au3)

    • Mars
    • 31. Januar 2023 um 11:47

    Ich glaube aktuell gehen ca. 20% der Zeit für simples "kopieren" (in EndScene, wenn die Structs befüllt werden), 20% für GDI+ und 50% für Matrixmultiplikationen und simple Mathematik und 10% fürs z-Buffer Sortieren drauf (bei "einem sehr großen Modell"). Gestoppt habe ich das nicht, ist nur eine Vermutung...

    Mir fallen auf anhieb einige stellen ein die man etwas aufbohen kann, wenn man eine dll oder asm nutzt, aber ich will erstmal schauen was man ohne diese Hilfsmittel rausholen kann. Klar in OpenGL eine primitiv beleuchtete Kugel mit 5000 Triangles anzuzeigen ist keine Kunst, in AutoIt ohne Hilfsmittel macht es deutlich mehr Spaß sowas zu machen :D

    Die vielen kaskardierten ORs sind doch eigentlich "der schnelle" Weg in AutoIt, oder? Einziges Problem in Test2 ist, dass meistens alle Vertices okay sind und daher die ersten 3 ORs nicht anschlagen können.

    Ein paar inner loops sind doof gelöst weil dort eigentlich nur der Mittelpunkt berechnet wird (z.B. in EndEscene -> Mittelpunkte berechnen & Sortieren), das kann man doppelt so schnell anderweitig lösen, oder 5x so schnell approximativ^^

    Im Lauf der Zeit hol ich nativ noch 20% performance raus... Dann schaue ich ob ich einige kritische Teile via inlineasm lösen kann. Und DANN baue ich einen "richtigen" Kugelgenerator (mit GUI und ganz vielen Slidern, sodass man nicht mehr von Hand im Code arbeiten muss wenn man seine Kugel designen will).

    M

  • ChatGPT für AutoIt - Talk, Ideen, Kuriositäten

    • Mars
    • 26. Januar 2023 um 22:28

    Ist wieder offtopic, aber das hat mich bei der Zusammenstellung der Regierung nach der Wahl gehörig aufgeregt: "Ministerium für Verkehr und Digitales". Was zum Teufel... Das sind doch vollkommen verschiedene Sachen und bei dem aktuellen Ausbaugrad der deutschen digitalen Infrastruktur und Bildung ist es mehr als nötig ein EIGENES Ministerium für Digitales zu haben, im Idealfall besetzt mit Leuten vom Fach die sich auskennen (da fallen mir ein paar Profs ein die "alles" wissen (auf ihrem jeweiligen Gebiet). Die wären für den Job perfekt. Vermutlich hätten sie aber verständlicherweise keine Lust :D). Stattdessen bekommen wir so ein paar windige Typen in nem windigen Ministerium wo "digitales" vollkommene Nebensache ist. Die fragen sich bestimmt ob die Cloud auch regnen kann.

    Lasst mich einfach Digitalminister werden. Ich hab einen Hass auf alles und keine Ahnung von "richtiger" Politik. Meine hinterzogenen Steuern kann ich auch selbst berechnen (Mathe kann ich ja). Das sind doch genau die Voraussetzungen die man braucht :D

  • ChatGPT für AutoIt - Talk, Ideen, Kuriositäten

    • Mars
    • 23. Januar 2023 um 16:04

    Ich frage mich halt immer wo die Logik hinter alldem ist. Man kann quasi alles zur Waffe umfunktionieren, oder irgendwie zweckentfremden, oder für (subjektiv) moralisch verwerfliche Sachen verwenden. Man muss doch langsam mal erkennen, dass "Vernunft" etwas ist das man nicht in Gesetze gießen kann. Vernunft verleitet dich dazu mit dem Brotmesser ein Brot (und nicht den Nachbarsjungen) zu schneiden, Vernunft verleitet dich dazu aus dem Nitratdünger keinen Böller zu bauen, sondern den Garten zu düngen. Aber bei all den Sachen ist es nicht das Gesetz das dich auf dem richtigen Weg hält, sondern dein Verstand.

    Ich bin einfach froh, dass ich anfang der 90ern geboren wurde, und wenigstens (vermutlich noch ein paar Jahre lang) mehr oder weniger tun und lassen kann was ich will, weil die Totalüberwachung und Verbotsliste noch nicht ausgereift genug ist. Ich will garnicht darüber nachdenken was in 50 Jahren los ist, wenn man einen KI assistenten hat der dir zu "allem" vorschreibt wie genau du was zu machen hast weil du sonst das Gesetz brichst^^ Vielleicht verknacken sie mich auch rückwirkend noch für etwas das ich bereits getan habe was in der zukünftigen Gesetzeslage als nicht verjährendes schweres Verbrechen gewertet wird, wer weiß :S. Ich bin mir jedenfalls keiner solchen Tat bewusst, aber das hat ja nichts zu heißen, ich weiß ja auch nicht was in 50 Jahren alles verboten ist ^^

    Edit: Da fällt mir ein, ich habe (vor langer Zeit. ca 10 Jahre, müsste verjährt sein) etwas illegales gemacht. Ich habe Rapsöl ins Diesel gemischt. Damals hat die Flasche noch 50ct gekostet (nicht 2-5€ wie heute) und es hat sich echt gelohnt das im Sommer 50/50 reinzukippen. Habe sogar verschiedene Mischungen gemacht und allesamt bei verschiedenen Temperaturen überprüft (Viskosität, Gefrierpunkt, etc) um für jede Temperatur die "optimale Mische" zu haben. Vermutlich haben das viele Leute so gemacht, denn schon nach kurzer Zeit gingen die Ölpreise im Discounter um 200% nach oben. Naja und die Diesel von Heute würden wahrscheinlich auch schluckauf bekommen, den alten Diesel hat das nicht gejuckt, der hat alles geschluckt. Vielleicht stinkt es ein wenig nach Frittenbude, aber das zeigt nur, dass man mit Stil unterwegs ist :rofl:

    Dafür will ich jetzt bitte in 50 Jahren ne Anzeige. You heared it here first.

    Gut dass wir hier im Forum bei Sonstiges/Talk sind, da stort man keinen beim Lästern^^

  • ChatGPT für AutoIt - Talk, Ideen, Kuriositäten

    • Mars
    • 23. Januar 2023 um 14:35

    Die Welt ist wirklich traurig... Etwas passt nicht in den Kram: Verbietet es!

    Ich frage mich immer warum sowas gemacht wird. Bildgenerierungs NNs (die ja durch unzählige interne Blockaden eh "handzahm" sind) sollen ja auch verboten/kontrolliert werden, weil sie unanständige Grafiken erzeugen können (auch welche die "wirklich" unanständig sind). Allerdings stellt sich mir da die Frage: Werde ich Pinsel und Farbe verbieten, weil ein Künstler damit etwas wirklich unanständiges malen kann? Werde ich Stifte verbieten, weil jemand damit etwas wirklich unanständiges schrieben kann? Werde ich Programmieren verbieten, weil man damit z.B. Viren erschaffen kann die millionenschwere Schäden verursachen können? Werde ich Sprache verbieten weil ich etwas wirklich unanständiges sagen kann?

    Kann ich einen Stift so konstruieren, dass man damit nur anständige Sachen schreiben kann? Oder einen Pinsel, dass man nur anständige Sachen zeichnen kann? Oder Sprache, dass man nichts falsches sagen kann?


    Meiner Meinung nach ist das Programm nur das Werkzeug. Was der Nutzer damit anfängt ist ihm selbst überlassen. Das Programm sollte "alles" können dürfen (genauso wie der Stift).

    Ist jetzt etwas OT, da es hier ja um Text und nicht um Bilder geht. Aber mich ärgert sowas. Der Anwender muss entscheiden, ob er dem, was der Bot ausspuckt, glauben schenkt (und ggf. selbst nachforschen). Es ist nicht möglich ein Programm zu entwickeln, das ausschließlich "die Wahrheit" sagt (alleine deshalb, weil "die Wahrheit" gar nicht existiert. Jede Beobachtung ist nur eine Projektion "der Wahrheit", je mehr Beobachtungen aus verschiedenen Richtungen wir anstellen, desto näher kommen wir "der Wahrheit", erreichen wird man sie aber nie, und das kann auch eine KI nicht). Der Anwender sollte sich dessen bewusst sein, und jegliche Antworten der KI kritisch hinterfragen.

  • ChatGPT für AutoIt - Talk, Ideen, Kuriositäten

    • Mars
    • 23. Januar 2023 um 12:45

    Wenigstens ist die KI im Entschuldigen erste Klasse. Davon könnten sich einige Leute (ich inklusive) eine Scheibe abschneiden. Am liebsten verteidige ich meine Irrtümer bis aufs Blut anstatt sie einzugestehen :S

    Wenn die KI allerdings nicht immer mit solchen steilen Thesen loslegen würde, müsste sie sich auch nur halb so oft entschuldigen ^^

  • Performance-Analyse der neuen Datenstruktur "Map"

    • Mars
    • 17. Januar 2023 um 11:56
    Zitat von AspirinJunkie

    Ein Zugriff auf ein Array-Elemente sollte IMMER schneller sein.

    Genau das ist mein Problem als ich darüber gestolpert bin... Wie kann ein Hashtable schneller sein als... "a * x + b" (Pointer an die richtige Stelle schieben ist eine lineare Funktion). Das will sich mir nicht erschließen. Im alten au3 Code könnte ich mich mal durchgraben wie die Implementierung konkret aussieht (vermutlich "nicht" einfach einen Pointer verschieben, sondern irgendwelcher furchtbar komplizierter Kram), aber Lust habe ich darauf nicht :D

    Zitat von Andy

    (ja, WÄHREND des Benchmarks^^) uswusf.

    Der Prozessor weiß eben wie man Powernapping betreibt. Der legt sich für ne Mikrosekunde hin und arbeitet danach direkt weiter ^^

    Zitat von AspirinJunkie

    sicher? :/ : ($a[$i])[$j]

    Da hab ich wieder nur den halben Text geschrieben, im Kopf war da irgendwo noch ein "ByRef" (das war genau mein Problem wofür ich ein Ticket geschrieben habe... Es gibt außer in Funktionsaufrufen keine Möglichkeit ByRef auf verschachtelte Arrays zuzugreifen).

    Beispiel:

    Code
    Local $m[], $m2[]
    $m[0] = $m2
    
    $m[0][1] = '[0][1]' ; <- ByRef Zugriff auf die verschachtelte Map
    $m[0][5] = '[0][5]' ; <-
    ConsoleWrite($m[0][1] & ' ' & $m[0][5] & @CRLF)


    Edit:

    Noch ein Test: $Array[Func()] ruft Func() immer 2x auf. Das wurde schon vor Ewigkeiten entdeckt. Die Devs haben dazu damals gesagt, dass das eben so ist weil es intern aus irgendwelchen Gründen so gemacht wird. Requests in die Richtung wurden abgelehnt. (Das schreibe ich gerade aus dem Gedächtnis, Links etc und konkrete Quellen habe ich keine parat).

    Interessanterweise ruft $Map[Func()] die Funktion aber nur 1x auf. Vielleicht liegt hier der Hase im Pfeffer? Wenn grundsätzlich Ausdrücke im Mapindex nur 1x ausgeführt werden, während es bei Arrays immer 2x ist, dann könnte das einiges erklären. Auch ein $Array[$i] hat vermutlich zwei Evaluationen von $i (ich kann nicht genau sagen, ob das doppelte Evaluieren "immer", oder nur für Funktionen passiert, da ich ja nicht überprüfen kann, ob $i 2x evaluiert wurde ohne eine Funktion zu verwenden die einen Zähler hochzählt oder einen Konsolenoutput hat), ein $Map[$i] hingegen (vermutlich) nur eine.

    Code
    Local $array[1], $map[]
    $array[0] = 0
    $map[0] = 0
    
    ConsoleWrite('Array: ')
    $array[Test()] = 1
    ConsoleWrite(@CRLF & 'Map:   ')
    $map[Test()] = 1
    ConsoleWrite(@CRLF)
    
    Func Test()
        ConsoleWrite('call ')
        Return 0
    EndFunc
    
    ; Output:
    ; Array: call call 
    ; Map:   call 
    Alles anzeigen


    Edit2:

    Noch mehr Tests: Scheinbar ist dieses Verhalten (doppeltes Evaluieren) inkonsistent. Das heißt "manchmal" wird es gemacht, und "manchmal" nicht...

    Das Erwartete Ergebnis im folgenden Code ist, dass Array[Array[Func()]] insgesamt 4x Func() aufruft. Es sind aber trotzdem nur 2x. Es zeigt sich, dass das innere $Array[Func()] nur 1x evaluiert, das äußere aber 2x (weshalb das innere 2x und nicht 4x evaluiert wird). Ich werde noch wahnsinnig... :/

    Code
    Local $array[1]
    
    ConsoleWrite('Array[Func()]:        ')
    $array[Test1()] = 0
    ConsoleWrite(@CRLF & 'Array[Array[Func()]]: ')
    $array[Test2() + $array[Test1()]] = 0
    ConsoleWrite(@CRLF)
    
    Func Test1()
        ConsoleWrite('test1 ')
        Return 0
    EndFunc
    
    Func Test2()
        ConsoleWrite('test2 ')
        Return 0
    EndFunc
    Alles anzeigen

    Edit3:

    Für Arrays gilt: Lesender Zugriff -> Index wird 1x evaluiert, Schreibender Zugriff -> Index wird 2x evaluiert (glaube ich).

    Edit4:

    Allerdings erklärt das nicht warum Maps beim lesenden Zugriff (in meinen Tests) ebenfalls schneller waren, obwohl Arrays hier keine Rechenzeit verschwenden.

    Genug Edits für heute...

    lg

    M

  • Performance-Analyse der neuen Datenstruktur "Map"

    • Mars
    • 17. Januar 2023 um 02:23

    Dann grabe ich mal einen Thread wieder aus der 200+ Tage alt ist :D

    Beim herumbasteln ist mir etwas seltsames untergekommen, und zwar schien es mir so, dass Maps via Integer-Indexzugriff schneller sind als Arrays via Integer-Indexzugriff (hier wird also nur die reine Performance geprüft NACHDEM das Array / die Map vollständig initialisiert ist, also mit Daten gefüllt wurde, bzw. der Datentyp innerhalb feststeht). Also habe ich mehrere kleine Tests gebastelt die alle einen Geschwindigkeitsvorteil zwischen 5% und 20% ergeben haben, und ich frage mich ob ich da etwas falsch mache, oder ob das wirklich so ist.

    Anbei ist ein halbwegs repräsentatives Beispiel.

    - Gegeben ist eine Liste aus 1000 Vektoren der Länge LEN.

    - Normiere alle Vektoren dieser Liste.

    -> Vektoren kann man als Array[LEN], oder als Map der Länge LEN implementieren

    -> Die 1000 Vektoren Liste kann man auch als Array, oder als Map implementieren

    -> Die Funktion "Normalize" ist identisch und kann ohne Codeänderung für Arrays und Maps verwendet werden.

    -> Das Beispiel wurde gewählt, da es zeigt was ich meine ohne "zu theoretisch" zu sein. Der viele Overhead (es sind ja nicht "nur" Map/Array Operationen, sondern Schleifen, Calls, Locals, etc) drückt das Ergebnis etwas, aber dafür ist es "realistischer" als meine anderen Tests.

    AutoIt
    ; AutoIt 3.3.16.1 Map vs Array Benchmark
    ; Es geht hier um die Zugriffszeiten NACHDEM die Map bzw. das Array initialisiert sind.
    
    Global $LEN = 30
    
    ;~ ConsoleWrite('Array' & @TAB & 'Map' & @CRLF)
    ;~ For $i = 0 To 99 Step 1
    ;~     $LEN = $i
        Bench()
    ;~ Next
    
    Func Bench($n = 1000)
    
        Local $a[$n], $m[]
        For $i = 0 To $n - 1 Step 1
            $a[$i] = VectorA()
            $m[$i] = VectorM()
        Next
        Local $t1 = TimerInit(), $t2 = TimerInit()
    
        $t1 = TimerInit()
        For $i = 0 To $n - 1 Step 1
            Normalize($a[$i])
        Next
        $t1 = TimerDiff($t1)
    
        $t2 = TimerInit()
        For $i = 0 To $n - 1 Step 1
            Normalize($m[$i])
        Next
        $t2 = TimerDiff($t2)
    
        ConsoleWrite('Time needed to normalize ' & $n & ' vectors of length ' & $LEN & ' in milliseconds' & @CRLF)
        ConsoleWrite('Array: ' & StringFormat('% 5.2f', $t1) & ' (100%)' & @CRLF)
        ConsoleWrite('Map:   ' & StringFormat('% 5.2f', $t2) & ' ('&Round($t2/$t1*100)&'%)' & @CRLF)
    
    ;~     ConsoleWrite($t1 & @TAB & $t2 & @CRLF)
    
    EndFunc
    
    Func VectorA()
        Local $a[$LEN]
        For $i = 0 To $LEN - 1 Step 1
            $a[$i] = Random()
        Next
        Return $a
    EndFunc
    
    Func VectorM()
        Local $a[]
        For $i = 0 To $LEN - 1 Step 1
            $a[$i] = Random()
        Next
        Return $a
    EndFunc
    
    Func Normalize(ByRef $a)
        Local $l = 0
        For $i = 0 To UBound($a) - 1 Step 1
            $l += $a[$i]^2
        Next
        $l = Sqrt($l)
        For $i = 0 To UBound($a) - 1 Step 1
            $a[$i] /= $l
        Next
    EndFunc
    Alles anzeigen

    Heraus kam, dass Maps (für diesen Anwendungsfall) zwischen 0% und 10% schneller sind als Arrays (je größer die Vektoren, desto schneller die Map). Kann das jemand reproduzieren, bzw. mit anderen Tests ergänzen/meinen Fehler finden? Falls man hier wirklich "einfach so" 10% rausholen kann indem man einfach die meisten Arrays in einem Skript durch Maps ersetzt, wäre das ziemlich praktisch. Dafür müsste man aber herausfinden "welche Operationen" auf Maps deutlich schneller sind (vielleicht sind es alle, vielleicht nicht? Zufälliger Indexzugriff etc. habe ich noch nicht getestet), und welche nicht. Bei Vektoren der Länge 3 ist der Unterschied quasi nonexistent (da macht der Overhead 80% der Laufzeit aus, daher sieht man hier nur sehr wenig), Vektoren der Länge 100 sind eher selten, das dient hier nur als Beispiel, weil man hier die vollen 10% sieht. Ein kleiner Bonus bei verschachtelten Maps ist, dass man darauf via $m[$i][$j] zugreifen kann (während man bei Arrays aufgeschmissen ist).

    unnamed.png

    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™