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

  • Select Cas in einem Intervall

    • Mars
    • 18. September 2024 um 12:21

    Es bringt halt leider auch Granaten wie das Folgende:
    grafik.png

    Halbe Seite Text

    grafik.png

    Dauert also noch etwas bis wir ersetzt werden :D

    (Bei der Frage habe ich implizit gehofft, dass mein Thread aus dem PU-Bereich gelesen wurde. Da ist ein Beispiel wie man die Pointer von (Globalen) AutoIt-Variablen durch ein paar Tricks herausbekommen kann)

    lg

    M

  • Select Cas in einem Intervall

    • Mars
    • 18. September 2024 um 11:49

    Einfach aus Jux habe ich die Frage mal in die KI gefüttert, und siehe da, der Code ist technisch gesehen korrigiert worden.

    grafik.png

    Irgendwann werden wir als Supporter überflüssig, es ist nur noch eine Frage der Zeit :)

    Edit: Habe noch nachgefragt, ob man an dem Code noch etwas ändern könnte, und tatsächlich, das zweimalige Verwenden von "left" wurde als potenzieller Fehler markiert.

    lg

    M

  • Ungefähre Funktionswerte Puffern

    • Mars
    • 1. Juli 2024 um 22:31

    Moin,

    wer kennt es nicht. Man hat eine Funktion die irgendetwas stochastisch berechnet (Monte-Carlo) und relativ lange braucht.

    Diese Funktion möchte man aber im Idealfall "oft" aufrufen (ggf. in einer anderen Funktion, die ebenfalls stochastisch arbeitet, usw usw). Im Endeffekt resultiert das in Abermillionen von Funktionsaufrufen, die sehr schnell sehr viel Zeit in Anspruch nehmen.

    Aber es gibt Abhilfe: Ein sich selbst füllender Puffer der Funktionswerte an einigen Stützstellen speichert und dann linear interpoliert (mit Unsicherheitsangabe).

    Vermutlich habe ich darin noch ein Paar Bugs versteckt, aber für meine bisherigen Anwendungsfälle hat es funktioniert, daher gibts jetzt ne "mini-UDF". Wie bei allen Methoden ist es wichtig "sinnvolle" Parameter zu wählen, ansonsten läuft sich der Algorithmus tot (mit Failsave -> MaxIter) oder produziert vollkommen falsche Ergebnisse (z.B. wenn man nur 10 Stützstellen verwendet, obwohl man eigentlich mindestens 100 braucht, oder wenn man eine Genauigkeit von 0.01 haben möchte, obwohl die Funktionswerte die Größenordnung 100 und eine große Streuung haben). Was die Ungenauigkeitsangabe im Returnwert angeht möchte ich meine Hand nicht ins Feuer legen. Da sich der Mittelwert ja mit jedem neuen Sample ändert und die vorherigen Varianzen nicht angepasst werden können (man will ja nicht "alles" speichern) ist dieser Wert nur "ungefähr richtig".

    Die Verwendung ist glaube ich intuitiv ersichtlich wenn man das Beispiel anschaut. FFB heißt "FuzzyFunctionBuffer"

    AutoIt
    Global Const $__FFB_MIN_SAMPLES = 17
    
    ; Beispielfunktion mit langer Rechenzeit die "nicht genau" arbeitet:
    ; Stochastisches abschätzen vom Volumen einer Kugel mir Radius $r
    Func myFunc($r)
    	Local Const $k = 1000
    	Local $n = 0, $r2 = $r ^ 2
    	For $i = 0 To $k - 1 Step 1
    		$n += Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 < $r2
    	Next
    	Return $n / $k * (2 * $r) ^ 3
    EndFunc   ;==>myFunc
    
    ; Naiver Ansatz:
    ; Einfach Mittelwert bilden über N Versuche (hier mit N = 100)
    ; Probleme:
    ; - Wie genau ist das denn jetzt?
    ; - Wenn ich die Funktionswerte mehrfach brauche muss ich mich selbst um das Puffern kümmern.
    ; - Wenn ich "ähnliche" Funktionswerte brauche muss die Funktion komplett neu ausgewertet werden.
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $v = 0
    	For $j = 0 To 99 Step 1
    		$v += myFunc($i / 100)
    	Next
    	$v /= 100
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f', $v) & ' err = ' & StringFormat('% 6.4f', $v-4/3*(($i/100)^3)*3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    ;~ ; Ansatz mit Lookup-Table & linearer Interpolation
    Local $FFB = _FFB_Create1D(myFunc, 0, 5, 100)
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $v = _FFB_Call1D($FFB, $i / 100, 0.01)
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * (($i / 100) ^ 3) * 3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    ; Der Trick ist jetzt, dass der LUT jetzt aufgebaut ist. Braucht man die Funktionswerte erneut ist das relativ schnell
    ; Auch für Funktionswerte die nicht "exakt" da liegen wo man schonmal gesampled hat. Je mehr sich der LUT füllt, desto schneller wird er.
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $x = $i / 100 + Random(-0.05, 0.05)
    	Local $v = _FFB_Call1D($FFB, $x, 0.01)
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $x) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * ($x ^ 3) * 3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    Func _FFB_Call1D(ByRef $FFB, $x, $nAccuracy = 0.01, $iIterMax = 100)
    	Local $iSteps = UBound($FFB) - 1
    	Local $k = ($x - $FFB[$iSteps][1]) / $FFB[$iSteps][2] * ($iSteps - 1)
    	Local $i = Int($k), $ix = ($i / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Unterer Slot
    	Local $j = $i + 1, $jx = ($j / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Oberer Slot
    	Local $alpha = $k - $i ; $alpha = Prozentsatz vom darüberliegenden Slot
    	Local $f = $FFB[$iSteps][0], $v = 0, $t = 0
    
    	If $i >= 0 And $i < $iSteps Then
    		If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($ix)
    				$FFB[$i][0] += $p[$_]
    			Next
    			$FFB[$i][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2
    			Next
    			$FFB[$i][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAccuracy
    			$v = $f($ix)
    			$FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1)
    			$FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2
    			$FFB[$i][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	EndIf
    
    	If $j >= 0 And $j < $iSteps Then
    		If $FFB[$j][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($jx)
    				$FFB[$j][0] += $p[$_]
    			Next
    			$FFB[$j][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$j][1] += ($p[$_] - $FFB[$j][0]) ^ 2
    			Next
    			$FFB[$j][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1) > $nAccuracy
    			$v = $f($jx)
    			$FFB[$j][0] = ($FFB[$j][0] * $FFB[$j][2] + $v) / ($FFB[$j][2] + 1)
    			$FFB[$j][1] += ($v - $FFB[$j][0]) ^ 2
    			$FFB[$j][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	EndIf
    
    	Local $Ret[]
    	If Abs($alpha) < 1E-3 Then
    		$Ret[0] = $FFB[$i][0]
    		$Ret[1] = Sqrt($FFB[$i][1] / ($FFB[$i][2] - 1))
    	ElseIf Abs($alpha - 1) < 1E-3 Then
    		$Ret[0] = $FFB[$j][0]
    		$Ret[1] = Sqrt($FFB[$j][1] / ($FFB[$j][2] - 1))
    	Else
    		$Ret[0] = $FFB[$i][0] * (1 - $alpha) + $FFB[$j][0] * $alpha
    		$Ret[1] = (Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1)) * $alpha
    	EndIf
    
    	Return $Ret ; [0] = Wert, [1] = Unsicherheit
    
    EndFunc   ;==>_FFB_Call1D
    
    Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100)
    	Local $_[$iSteps + 1][3]
    	$_[$iSteps][0] = $xFunc
    	$_[$iSteps][1] = $fMinInclusive
    	$_[$iSteps][2] = $fMaxInclusive - $fMinInclusive
    	; [0] = Mittelwert
    	; [1] = VarianzSumme
    	; [2] = NumSamples
    	Return $_
    EndFunc   ;==>_FFB_Create1D
    Alles anzeigen


    Edit: Hier noch eine Überarbeitung mit quadratischer Interpolation (so kann man den LUT etwas kleiner wählen, oder man möchte eine sehr weiche Kurve. Die gab es bei der linearen Version nicht).

    AutoIt
    #include <Array.au3>
    
    Global Const $__FFB_MIN_SAMPLES = 17
    Global Const $__FFB_NUM_MAXITER = 100
    
    ; Anwendungsfall: Funktionswerte entstören
    Func myFunc($r)
    	Return Sin($r) + Random() / 3 ; sin ist im Bereich -1 bis 1, mit 1/3 plusminus rauschen ist das schon ziemlich viel.
    EndFunc   ;==>myFunc
    
    Local $FFB = _FFB_Create1D(myFunc, -10, 10, 100) ; Hat 100 Slots zwischen -10 und 10
    For $i In __FFB_Range('[', -3.141, 3.141, ']', 200) ; Die 200 Samples brauchen nur ca. 33 Slots. Durch die quadratische Interpolation kommt trotzdem eine gute Kurve heraus.
    	Local $v = _FFB_Call1D($FFB, $i[1], 0.0005, 1e9, 100000) ; Wenn man es wirklich ganz genau haben will. (0.0005 Sigma, da will man schon 3 richtige Nachkommastellen haben)
    	ConsoleWrite(StringFormat('% 5.3f', $i[1]) & ', ' & StringFormat('% 6.4f', $v[0])  & @CRLF)
    Next
    _ArrayDisplay($FFB) ; Nachschauen was im LUT eigentlich drin steht.
    
    Func _FFB_Train1D(ByRef $FFB, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9)
    	Local $iSteps = UBound($FFB) - 1
    	Local $fMin = $FFB[$iSteps][1]
    	Local $fMax = $FFB[$iSteps][2] + $FFB[$iSteps][1]
    	Local $bTargetMet = True, $v = 0
    	Do
    		$bTargetMet = True
    		For $i In __FFB_Range('[', $fMin, $fMax, ']', $iSteps)
    			$v = _FFB_Call1D($FFB, $i[1], $nAbsAccuracy, $nRelAccuracy)
    			If $v[1] > $nAbsAccuracy Then $bTargetMet = False
    			If $v[0] > 1E-9 And $v[1] / $v[0] > $nRelAccuracy Then $bTargetMet = False
    		Next
    	Until $bTargetMet
    EndFunc   ;==>_FFB_Train1D
    
    Func _FFB_Call1D(ByRef $FFB, $x, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9, $iIterMax = $__FFB_NUM_MAXITER, $bQuadraticInterpolation = True)
    	Local $iSteps = UBound($FFB) - 1, $s5 = $iSteps - 5, $s5d = $s5 / $FFB[$iSteps][2]
    	Local $k = ($x - $FFB[$iSteps][1]) * $s5d + 2, $ik = Int($k) ; Slots: [ik-1, ik, ik+1, ik+2] <- diese 4 sind immer vorhanden.
    	Local $alpha = $k - $ik ; $alpha = Prozentsatz vom darüberliegenden Slot
    	Local $f = $FFB[$iSteps][0], $v = 0, $t = 0
    	For $i = $ik - 1 To $ik + 2 Step 1 ; from -1 to 2 -> Für 4 Slots.
    		Local $ix = ($i - 2) / $s5d + $FFB[$iSteps][1]
    		If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($ix)
    				$FFB[$i][0] += $p[$_]
    			Next
    			$FFB[$i][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2
    			Next
    			$FFB[$i][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAbsAccuracy Or ($FFB[$i][0] > 1E-9 And Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) / $FFB[$i][0] > $nRelAccuracy)
    			$v = $f($ix)
    			$FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1)
    			$FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2
    			$FFB[$i][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	Next
    	Local $Ret[]
    	If $bQuadraticInterpolation Then
    		Local $ixa = ($ik - 3) / $s5d + $FFB[$iSteps][1], $ixb = ($ik - 2) / $s5d + $FFB[$iSteps][1], $ixc = ($ik - 1) / $s5d + $FFB[$iSteps][1], $ixd = $ik / $s5d + $FFB[$iSteps][1]
    		Local $P3L = __FFB_Func3P($ixa, $FFB[$ik - 1][0], $ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0])
    		Local $P3H = __FFB_Func3P($ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0], $ixd, $FFB[$ik + 2][0])
    		$Ret[0] = ($P3L[0] * $x^2 + $P3L[1] * $x + $P3L[2]) * (1 - $alpha) + ($P3H[0] * $x^2 + $P3H[1] * $x + $P3H[2]) * $alpha
    	Else
    		$Ret[0] = $FFB[$ik][0] * (1 - $alpha) + $FFB[$ik + 1][0] * $alpha
    	EndIf
    	$Ret[1] = (Sqrt($FFB[$ik][1]) / ($FFB[$ik][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$ik + 1][1]) / ($FFB[$ik + 1][2] - 1)) * $alpha
    	Return $Ret ; [0] = Wert, [1] = Unsicherheit
    EndFunc   ;==>_FFB_Call1D
    
    Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100, $nBorderEpsilon = 1E-6)
    	$fMinInclusive -= $nBorderEpsilon
    	$fMaxInclusive += $nBorderEpsilon
    	Local $_[$iSteps + 1][3]
    	$_[$iSteps][0] = $xFunc
    	$_[$iSteps][1] = $fMinInclusive
    	$_[$iSteps][2] = $fMaxInclusive - $fMinInclusive
    	; [i][0] = Mittelwert
    	; [i][1] = VarianzSumme
    	; [i][2] = NumSamples
    	Return $_
    EndFunc   ;==>_FFB_Create1D
    
    Func __FFB_Range($sLeft = '[', $fMin = 0, $fMax = 1, $sRight = ']', $iSteps = 10)
    	Local $a[$iSteps], $_[2], $l = $sLeft = '[' ? 0 : 1, $s = ($fMax - $fMin) / ($iSteps - 1 + ($sRight = ']' ? 0 : 1) + $l)
    	For $i = 0 To $iSteps - 1 Step 1
    		$_[0] = $i
    		$_[1] = ($i + $l) * $s + $fMin
    		$a[$i] = $_
    	Next
    	Return $a
    EndFunc   ;==>__FFB_Range
    
    Func __FFB_Func2P($x0, $y0, $x1, $y1)
    	Local $_[] ; f(x) = ax + b
    	$_[0] = ($y1 - $y0) / ($x1 - $x0)
    	$_[1] = $y0 - $_[0] * $x0
    	Return $_
    EndFunc
    
    Func __FFB_Func3P($x0, $y0, $x1, $y1, $x2, $y2)
    	Local $_[] ; f(x) = ax² + bx + c
    	$_[0] = ($x2 * ($y1 - $y0) + $x1 * ($y0 - $y2) + $x0 * ($y2 - $y1)) / (($x0 - $x1) * ($x0 - $x2) * ($x1 - $x2)) ; a
    	$_[1] = (($y1 - $y0) + $_[0] * ($x0 ^ 2 - $x1 ^ 2)) / ($x1 - $x0) ; b
    	$_[2] = $y0 - $_[0] * $x0 ^ 2 - $_[1] * $x0 ; c
    	Return $_
    EndFunc
    Alles anzeigen


    lg

    M

  • RAM-Typ auslesen

    • Mars
    • 25. Juni 2024 um 17:12
    Zitat von water

    In der deutschen Übersetzung fälschlich "Blitz"

    Jedes Mal, wenn ich auf der MS Seite etwas nachschlage und diese furchtbaren deutschen Übersetzungen (teilweise von Naturkonstanten wie "BLACKNESS" beim BitBlt) sehe, klicke ich "diese Seite war nicht hilfreich" an und schreibe in den Kommentar rein, dass sämtliche Wörter die mit Programmcode zu tun haben bitte nicht übersetzt werden sollen. Ich hab schon Tabellen mit Enums gesehen die man von Start bis Ende in die Tonne treten konnte weil fast alle Bezeichnungen falsch waren X/

    Ist denen aber egal. Wenn ich nicht 90% der Namen von Sachen die ich dort suche schonmal gehört hätte wäre ich echt sauer, aus genanntem Grund bin ich nur "genervt" von sowas...

    M

  • [GDI+] Kurve zeichnen (3 Methoden)

    • Mars
    • 4. Juni 2024 um 15:45

    Moin,

    wer kennt es nicht: Ich möchte eine Funktion f(t) -> (x(t),y(t)) zeichnen und wähle einfach 100 gleichverteilte Punkte in t um das zu tun. Das Ergebnis sieht mies aus. Ich wähle 200 Punkte. Immernoch mies. 1000 vielleicht? Okay, jetzt sieht es OK aus, aber weil meine Kurve irgendwo ein paar fiese Kanten & Peaks hat ist das Ergebnis immernoch nicht Pixelgenau... Also 10000 Punkte?

    Anbei ist ein Skript mit 3 Methoden um eine Kurve zu zeichnen.

    1. Linear (das was oben beschrieben wurde, 1 f(t) call pro Punkt)

    2. Adaptiv (Zunächst mit niedriger Auflösung Linear, dann "schätzen" wo gute Orte für weitere Punkte sind, 1 f(t) call pro Punkt)

    3. Adaptiv2 (Es wird mehr oder weniger via BruteForce herausgefunden wo gute Orte für weitere Punkte sind, "viele" f(t) calls pro Punkt)

    Es sei angemerkt, dass nicht jede Funktion für jeden Anwendungsfall sinnvoll ist. 1 & 2 eignen sich für Echtzeitanwendungen (sie brauchen für ~100 Punkte nur ein paar Millisekunden, je nach PC). 3 ist dafür geeignet wenn man die Funktion mit den wenigst möglichen Punkten "nahezu" bestmöglich abbilden will und die benötigte Zeit keine Rolle spielt (z.B. wenn man die Punkte irgendwo puffert, dann muss man sie nur 1x berechnen und kann sie anschließend relativ performant anzeigen, weil es so wenige sind).

    Die Geschwindigkeit ist leider ziemlich mies, da ich an einigen Stellen faul war (z.B. lineare Liniensuche statt Newton, etc.). Außerdem fehlen mir gewisse Datenstrukturen in AutoIt die ich, mangels Pointersupport, auch nicht nachbauen konnte (bzw. ich war einfach zu faul alles via DllStruct zu machen).

    PS: Jede Funktion f(x) = ... lässt sich als f(x) = (x, y(x)) umschreiben, wie auch im Beispiel verwendet. Man muss also nicht zwingend f:R->R² Funktionen verwenden :)

    unnamed.png


    Edit: Um zu demonstrieren, dass es auch mit "echten" R² Funktionen klappt kann man z.B. sowas hier verwenden:

    Code
    Func F($t)
    	Local $__[]
    	$__[0] = $t * $iGuiW * 0.9 + $iGuiW * 0.05
    	$__[1] = 50 * ManyGauss($t * 100 - 60) + 100*(2*$t-1)^2
    	Local $a = 0.1, $cx = $iGuiW / 2, $cy = 0
    	Local $_[]
    	$_[0] = $cx + ($__[0] - $cx) * Cos($a) - ($__[1] - $cy) * Sin($a)
    	$_[1] = $cy + ($__[0] - $cx) * Sin($a) + ($__[1] - $cy) * Cos($a)
    	Return $_
    EndFunc

    unnamed2.png

    Eine gewöhnliche f(x) -> R Funktion könnte soetwas nicht abbilden, da einige x-Werte mehrere y-Werte besitzen. Fälle die in diesem Skript "nicht" abgedeckt sind, sind unstetige Funktionen. Falls es irgendwo einen "echten" Sprung in der Funktion gibt (z.B. Funktionen die aus mehreren Teilen bestehen die in einem Plot zu mehreren Linien führen), kann die hier gezeigte Methode nicht verwendet werden.


    lg

    M

    Dateien

    AdaptiveDiscretization.au3 14,53 kB – 438 Downloads
  • Zeitreihe Regressionsanalyse Trendberechnung

    • Mars
    • 30. Mai 2024 um 22:47

    Meine Frage wäre: Was möchtest du konkret aus den Daten herauslesen?
    Soweit ich das verstehe sind die Daten wie folgt: Eintrag1 = [#Artikelnummer1 #Ankaufszahl1 #Verkaufszahl1, #DatumBzwZeitraum1, #WeitereInfos1], ... usw. für tausende Produkte und verschiedene Zeitpunkte/Zeiträume.

    Eine übliche Methode um ein Gefühl für Große Datenmengen zu bekommen ist erstmal die Ansicht verschiedener Scatterplots/Heatmaps (z.B. x-Achse = Datum, y-Achse = Verkaufszahl, Fabcode = Produkttyp. Hier muss man einiges an Kombinationen durchprobieren). Darin ergeben sich dann eindeutige Muster (je nachdem wie man den Plot parametrisiert), die man anschließend weiter auswerten kann.

    Bin aber nicht sicher, ob dir hier AutoIt weiterhelfen kann... Also einen Scatterplot kann man schnell und einfach basteln, aber das kann z.B. Gnuplot ebenfalls (ganz ohne Programmieraufwand). Die "Analyse" wird sich bei AutoIt auch auf lineare Regression einzelner Plotabschnitte beschränken (siehe oben), der Informationsgewinn hält sich dabei aber in Grenzen. Den Trend erkennt man ja schon am Plot.

    Edit: Falls du Trends extrapolieren willst wird es auch eher knifflig und ich vermute da bist du bei Machine-Learning-Leuten besser aufgehoben. Die kennen sich mit Voodoo aus :D

    lg
    M

  • _ConsoleWriteMap

    • Mars
    • 21. Mai 2024 um 12:32

    Sieht fast genauso aus wie etwas das ich immer verwende um Maps in die Konsole zu verfrachten :D

    Falls gemischte Keys (Integer-Keys & String-Keys) verwendet werden ist hier noch eine kleine Ergänzung:

    $sOut &= StringFormat('%s%-20s%s%s\n', $aC[$n], (IsString($k) And StringIsInt($k)) ? '"' & $k & '"' : $k, $vValue).

    Damit sieht man eindeutig womit man es zu tun hat.

    lg

    M

  • Rollende Kugel mit Textur

    • Mars
    • 18. Mai 2024 um 11:21

    Das ist ein super Beispiel. Hier wird Die Kugel einfach "Scheibchenweise" mit einer linearen Matrix gezeichnet, sodass insgesamt der Eindruck entsteht man hätte es irgendwie nichtlinear gelöst. Dafür muss man aber ein Sleep(100) einbauen und $iStep = 15 setzen, sonst sieht man das nicht weil es zu schnell und zu fein aufgelöst ist :D

  • Rollende Kugel mit Textur

    • Mars
    • 18. Mai 2024 um 01:58

    Sehr interessant. Hier noch eine Idee: Finde eine Transformation um die Einzelpixelrechnung komplett aus dem Spiel zu nehmen.

    Der Texturabdruck dieser Formel ist auch nicht ganz richtig für eine "korrekte" perspektivische Projektion einer Ebene auf eine Kugeloberfläche (Das Abbild ist eine um 45° gedrehte Raute). Da ich hier kein Profi bin ist Folgendes nur eine Vermutung: Die 3x2 Matrizen aus GDI+ werden hierfür wahrscheinlich nicht reichen, weil sie die Verzerrung nicht abbilden können. Dafür müsste man dann doch wieder nichtlineare Elemente einbringen die GDI+ nicht abbilden kann sodass man sie doch von Hand ausrechnen muss... Ist wahrscheinlich im Endeffekt kein Vorteil, aber ganz kurz dachte ich "vielleicht reicht die GDI+ übliche Matrix ja doch". Bin da kein Profi, von daher: Vielleicht bringt die Idee ja irgendwen weiter :D

    Den Texturfootprint kann man mit folgendem Skript einsehen:

    AutoIt
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    
    OnAutoItExitRegister(_exit)
    Opt("GUIOnEventMode", 1)
    
    Global Const $PI = ACos(-1), $PI_2 = ASin(1), $PI_4 = ATan(1), $_2PI = $PI + $PI
    
    main()
    
    
    
    Func main()
    	Local $mC = _b3d_createCanvas(1000, 750)
    
    	; start moving textured ball
    	Local $mTexture = _b3d_importTexture(@ScriptDir & "\13h_310x156.bmp")
    	_b3d_ballMoving($mC, 50, 1000/2, 750/2, 0, 0, $mTexture)
    
    	; GUI endless loop
    	While Sleep(100)
    	WEnd
    
    EndFunc
    
    ; demo function for drawing a moving ball
    Func _b3d_ballMoving(ByRef $mCanvas, Const $iRadius, Const $iXStart, Const $iYStart, $fVx, $fVy, $mTexture, Const $fRotX0 = 0, Const $fRotY0 = 0)
    	Local $iXPos = $iXStart, $iYPos = $iYStart
    	Local $fRotX = $fRotX0, $fRotY = $fRotY0
    	Local $fU = 2 * $PI * $iRadius
    
    	Local $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\13h_310x156.bmp")
    	Local $aSize = _GDIPlus_ImageGetDimension($hBitmap)
    	Local $hCopy = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $aSize[0], $aSize[1])
    	Local $hGFX = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    	Local $i = 0
    	Local $hPEN = _GDIPlus_PenCreate(0xFF808080, 3)
    	Do
    		$fVx = Sin($i/30)
    		$fVy = Cos($i/30)
    		$i += 1
    		; clear old image
    		_GDIPlus_GraphicsClear($mCanvas.Context, 0xFF303030)
    
    		_GDIPlus_GraphicsDrawImageRect($hGFX, $hCopy, 0, 0, $aSize[0], $aSize[1])
    
    		; draw textured sphere
    		_b3d_drawTexturedSphere($mCanvas, $iXPos, $iYPos, $iRadius, $mTexture, $fRotX, $fRotY, $hBitmap)
    
    		_GDIPlus_GraphicsDrawImage($mCanvas.Context, $hBitmap, 10, 550)
    
    
    		_b3d_canvasShow($mCanvas)
    
    		$iXPos += $fVx
    		$iYPos += $fVy
    		$fRotX += __b3d_modPos($fVy, $fU) / $fU * $_2PI
    		$fRotY -= __b3d_modPos($fVx, $fU) / $fU * $_2PI
    
    
    	Until $iXPos > 90000
    	_GDIPlus_PenDispose($hPEN)
    	_GDIPlus_BitmapDispose($hBitmap)
    	_GDIPlus_BitmapDispose($hCopy)
    EndFunc
    
    
    ; draws a sphere and map a texture on it
    Func _b3d_drawTexturedSphere(ByRef $mCanvas, $iMx, $iMy, $iR, $mTexture, $iRotX = 0, $iRotY = 0, $hTexture = 0)
    	Local $iTexWidth = $mTexture.width
    	Local $iTexHeight = $mTexture.height
    	Local $iX, $iY, $iHalfChord, $iSegmentHeight
    	Local $fXTex, $fYTex
    	Local $iColor
    	Local $aBitmap = $mTexture.Pixels ; faster than _GDIPlus_BitmapGetPixel
    	Local $hBitmap = $mCanvas.Bitmap
    
    	; Koordinaten-Transformation als LUT um Doppelberechnung zu vermeiden
    	; Zum jeweiligen aktuellen Kreissegment (Radius - aktuelle Position im Kreis) wird die dazugehörige Koordinate im Texturraum berechnet
    	Local $aTexCoordsY[$iR + 1][2]
    	Local $aTexCoordsX[$iR + $iR + 1]
    	Local $fRad, $fRadX, $fRadY, $fRadYBottom
    	For $iH = 0 To $iR
    		; der Kreisbogenabstand vom Zenitpunkt (=Kugelwinkel in rad)
    		$fRad = ASin(($iR-$iH) / $iR)
    
    		; upper half
    		$fRadY = $fRad + $iRotX
    		$aTexCoordsY[$iH][0] = Round(__b3d_modPos($PI_2 - $fRadY, $Pi) / $Pi * ($iTexHeight - 1))
    
    		; lower half
    		$fRadYBottom = $fRadY - $fRad - $fRad
    		$aTexCoordsY[$iH][1] = Round(__b3d_modPos($PI_2 - $fRadYBottom, $Pi) / $Pi * ($iTexHeight - 1))
    
    		; left half
    		$fRadX = $PI - $fRad + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren
    		$aTexCoordsX[$iH] = Round(__b3d_modPos($fRadX , $_2PI) / $_2PI * ($iTexWidth - 1))
    
    		; right half
    		$fRadXRight = $fRad + $PI + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren
    		$aTexCoordsX[$iR + $iR - $iH] = Round(__b3d_modPos($fRadXRight, $_2PI) / $_2PI * ($iTexWidth - 1))
    	Next
    
    	; middle line (extra to avoid double processing):
    	$iYTexMid = $aTexCoordsY[$iR][0]
    	For $iX = $iMx - $iR To $iMx + $iR
    		$fXTex = $aTexCoordsX[$iX - $iMx + $iR]
    		$iColor = $aBitmap[$fXTex][$iYTexMid]
    		DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $iYTexMid , "uint", 0xFF00FFFF)
    		DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iMy, "uint", $iColor) ; faster than extra _GDIPlus_BitmapSetPixel()
    	Next
    
    	; rest of circle area
    	For $iSegmentHeight = 0 To $iR - 1
    
    		; halbe Sehnenlänge
    		$iHalfChord = Int(Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight))))
    
    		; Koordinaten des Quellpixels aus dem Texturbitmap
    		$fYTex = $aTexCoordsY[$iSegmentHeight][0]
    		$fYTexBottom = $aTexCoordsY[$iSegmentHeight][1]
    
    		For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord
    			$fXTex = $aTexCoordsX[$iX - $iMx + $iR]
    
    			; draw top case
    			$iColor = $aBitmap[$fXTex][$fYTex]
    			$iY = $iMy + $iSegmentHeight - $iR
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTex , "uint", 0xFF00FFFF)
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor)
    
    			; draw bottom case
    			$iColor = $aBitmap[$fXTex][$fYTexBottom]
    			$iY = $iMy - $iSegmentHeight + $iR
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTexBottom , "uint", 0xFF00FFFF)
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor)
    		Next
    	Next
    EndFunc
    
    
    Func _b3d_importTexture($sPath)
    	Local $mTexture[]
    	Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sPath)
    	$mTexture.Bitmap = $hBitmap
    	If @error Then Return SetError(@error, @extended, Null)
    
    	$mTexture.width = _GDIPlus_ImageGetWidth($hBitmap)
    	$mTexture.height = _GDIPlus_ImageGetHeight($hBitmap)
    
    	; convert to AutoIt-Array for faster pixel access
    	Local $aBitmap[$mTexture.width][$mTexture.height], $x, $y
    	For $x = 0 To $mTexture.width - 1
    		For $y = 0 To $mTexture.height - 1
    			$aBitmap[$x][$y] = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y)
    		Next
    	Next
    	$mTexture.Pixels = $aBitmap
    
    	Return $mTexture
    EndFunc
    
    ; function to draw a filled circle on a bitmap
    Func _b3d_drawCircleFilled(ByRef $mCanvas, $iMx, $iMy, $iR, $sColor = "0xFFFFFFFF")
    	Local $iX, $iY, $iHalfChord, $iSegmentHeight
    
    	; middle line (extra to avoid double processing):
    	For $iX = $iMx - $iR To $iMx + $iR
    		_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iMy, $sColor)
    	Next
    
    	; rest of circle area
    	For $iSegmentHeight = 0 To $iR - 1
    		$iHalfChord = Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight)))
    
    		For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord
    			$iY = $iMy + $iSegmentHeight - $iR
    			_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor)
    			$iY = $iMy - $iSegmentHeight + $iR
    			_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor)
    		Next
    	Next
    EndFunc
    
    ; zeigt den aktuellen Zustand der Canvas (des Zeichnungsbitmaps an)
    Func _b3d_canvasShow(ByRef $mCanvas)
    	_GDIPlus_GraphicsDrawImage($mCanvas.Graphic, $mCanvas.Bitmap, 0, 0)
    EndFunc
    
    Func _b3d_createCanvas($iWidth, $iHeight)
    	; map which holds all the necessary parameters
    	Local $mCanvas[]
    	$mCanvas.width = $iWidth
    	$mCanvas.height = $iHeight
    
    	; Initialize GDI+ library
        _GDIPlus_Startup()
    
    	; create GUI
        $mCanvas.GUI = GUICreate("Ball 3D", $iWidth, $iHeight)
    	GUISetBkColor(0x303030, $mCanvas.GUI) ;set GUI background color
    	GUISetOnEvent($GUI_EVENT_CLOSE, _exit)
    	GUISetState(@SW_SHOW, $mCanvas.GUI)
    
    	; create Canvas
    	$mCanvas.Graphic = _GDIPlus_GraphicsCreateFromHWND($mCanvas.GUI)
    	$mCanvas.Bitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $mCanvas.Graphic)
    	$mCanvas.Context = _GDIPlus_ImageGetGraphicsContext($mCanvas.Bitmap)
    
    	Return $mCanvas
    EndFunc
    
    ; positive modulo
    Func __b3d_modPos($divident, $divisor)
    	Local $m = Mod($divident, $divisor)
    	Return $m < 0 ? $m + $divisor : $m
    EndFunc
    
    Func _exit()
    	_GDIPlus_Shutdown()
    	Exit
    EndFunc
    Alles anzeigen

    lg

    M

  • Frage zu seltsamen Verhalten von _WinAPI_CopyFileEx

    • Mars
    • 16. Mai 2024 um 21:37
    Zitat von hipfzwirgel

    p.s. für einen Hook hat MS ja 4ms als Wert festgelegt. Also müsste schon bei 10ms eigentlich die Progressproc abbrechen...

    Hinweis: Das "Sleep()" von AutoIt kann keine kleineren Schritte als 10ms verwenden. Du kannst zum Spaß mal 1000x Sleep(4) laufen lassen und jeweils mit TimerInit & Timerdiff stoppen wie viel Zeit tatsächlich geschlafen wurde. Leider funktionieren auch alternative Methoden wie delayexecution oder nanosleep mit AutoIt nicht zuverlässig (manchmal schon, manchmal aber auch nicht... Zumindest nach meiner Erfahrung).

    Das hilft dir jetzt nicht bei deinem Problem, aber die Info wollte ich loswerden, nicht dass du versuchst "Sleep(4)" anzuwenden und dich dann wunderst was hier eigentlich los ist :D


    lg

    M

  • Holen Sie sich aus den Ressourcen der ausführbaren Dateien Daten in Form einer Zeile ab

    • Mars
    • 13. April 2024 um 13:08

    The problem is:
    - This is impossible as long as noone knows everything about map/struct itself (what exactly is TdlgDXImages2, Font, TcxImageList, etc.). You cannot assemble a mapping without knowing all members.
    - This looks like a "map" from another programming language. If "everything" is known one might construct something with nested maps (in AutoIt) to represent the data but the memory layout will be vastly different. Also AutoIt does not allow to reinterpret_cast<map*>(ptr), so noone will be able to even get a memory dump of a map here (and vice versa) :D. A dedicated function to r/w is needed.
    - Wrapping this into a "struct" requires the knowledge of the whole memory layout. This is impossible, especially for maps with variant datatypes or other "unknown inner workings" like: What exactly is "[]" in memory? This looks like an empty list but only god knows how this is represented in RAM (assuming the shown binary data is a memory dump).
    - etc.

    Most people here are skilled in reading/writing code but I fear your request cannot be fulfilled by anyone without "the whole picture".

    To sum it up:
    - If "everything" about this map is known, it is possible to write a "ReadBinaryToNestedMap/WriteNestedMapToBinary" function.
    - If you find someone who wants to do this (after "everything" is known) is another story.

    M

  • Einfaches Preprocessing zum Komprimieren (nur eine Spielerei)

    • Mars
    • 3. April 2024 um 01:17

    Mit Ausgangspunkt ist gemeint, dass man das als Vorstufe für einen Kompressionsalgorithmus verwenden kann. Üblicherweise bekommt man eine bessere Kompression, wenn irgendeine Struktur in den Daten vorliegt die man ausnutzen kann. In diesem Fall: Sehr viel mehr Nullen als Einsen, dafür aber etwas unstrukturierter. (Ist also für einen Kodierer der Muster erkennt ungeeignet, die Muster wurden ja quasi in Nullen umgewandelt)

    Mögliche Folgeschritte wären:
    - Lauflängenkodierung (ist intuitiv das erste was mir einfällt)
    - Falls Lauflängenkodierung im Binärformat -> Arithmetische Entropiekodierung als Folgeschritt (huffman geht hier nicht besonders gut, da die Symbole nicht mehr aligned sind).
    - Falls Lauflängenkodierung mit Tokens -> Irgendeine Entropiekodierung (hier hat man die Symbole einzeln -> Jede Methode geht) als Folgeschritt -> Fertig.

    Probleme der aktuellen Methode:
    - Je größer der LUT, desto länger ist die Warmlaufphase, da der LUT erstmal gefüllt werden muss
    - Je größer der LUT, desto besser das Ergebnis nach der Warmlaufphase, aber man ist auf 16 Bit beschränkt.

    Lösungsansatz den ich irgendwann ausprobiere:
    - Baue einen beliebig großen "pseudo" LUT aus mehreren 8Bit Blöcken zusammen.
    - So siehts aus: [Block n-2][Block n-1][Block n][Bit x] -> Akuell wird nur [Block n] verwendet um x vorherzusagen. Man könnte allerdings auch alle anderen Blöcke einbeziehen. Da hier (aus Stochastik-Sicht) keine Unabhängigkeit vorliegt (es ist also ein Unterschied ob ich ausgehend von [Block n-1 (8Bit)] und [Block n (8Bit)] das x vorhersage, oder ob ich einen einzigen 16Bit Block nehme) muss man für halbwegs gute Ergebnisse vermutlich eine Art Interleaving verwenden.

    Trivialbeispiel mit 4 x 8Bit Blöcken -> [aaaaaaaa][bbbbbbbb][cccccccc][dddddddd][x] -> 4 Vorhersagen mit den Blöcken ohne Änderung (habe keine Nummern drangeschrieben, die aaaaaaaa sind eigentlich a1a2a3...usw)
    Zusätzlich mit Interleaving [abcdabcd][abcdabcd][abcdabcd][abcdabcd][x] -> 4 Weitere Vorhersagen für x
    Eine Linearkombination (mit irgendwelchen Koeffizienten die ich nicht kenne) dieser 8 Vorhersagen dient als Approximation der Vorhersage die ein einziger 32Bit Block liefern könnte. Je mehr Vorhersagen mit verschieden Verwobenenen 8 Bit Blöcken man verwendet, desto besser die Approximation. Gleichzeitig sinkt die Warmlaufphase, da man nicht 2^32 Zustände, sondern (im Beispielfall) nur 8 * 2^8 = 2048 Zustände vollmachen muss. Ich schätze damit sind auch bei "normalem Text" 90%+ Nullen möglich (statt 79%). Wäre zumindest lustig, wenn das gehen würde :)

    Danach kommt die "swap Methode" (aus dem Permutationen Komprimieren Thread) zum Einsatz (wobei hier die Nullen und Einsen geswappt werden um sie zu sortieren). Dann sind die Daten in folgender Form: [Bits zur Steuerung der Swaps][alle Einsen][alle Nullen]. Alle Einsen und Alle Nullen können als 2 Integer gespeichert werden, sodass die komprimierten Daten nur noch aus Swap-Positionen + 2 Int bestehen. Hehehe. Damit werde ich die Welt erobern.

    M

  • Einfaches Preprocessing zum Komprimieren (nur eine Spielerei)

    • Mars
    • 2. April 2024 um 17:53

    Moin,

    habe neulich nochmal über die LZ77 Methode nachgedacht und überlegt, dass man einen ähnlichen Effekt vermutlich auch deutlich einfacher bekommen kann. Die Idee ist folgendes:

    - Die Daten sind Binär '010101...' und wir wollen eine "Mustererkennung" ohne wirklich irgendwas zu rechnen.

    - Baue einen Lookuptable auf, der für jede Bitfolge (von z.B. 8 Bit) angibt, wie wahrscheinlich eine "0" oder eine "1" auf diese 8 Bit folgt.

    - Laufe alle Daten durch und ersetze sie durch "0" oder "1", je nachdem ob die Vorhersage gestimmt hat. Aktualisiere den LUT entsprechend nach jedem Schritt.

    - Das Ganze ist trivial reversibel.

    - Für einen Lookuptable mit >8Bit wird eine Map mit Stringkeys verwendet (das ist langsam). Falls man das mal in einer anderen Sprache programmiert müsste die Methode extrem schnell sein (es ist im Prinzip nur triviales Bitgeschiebe und Lookups), sollte auch ASM-freundlich sein.

    - Aktuell wird nichts komprimiert, sondern nur "die Anzahl der Nullen in den Binären Daten maximiert". Vielleicht kann man die Methode aber für irgendwas als Ausgangspunkt verwenden (z.B. Lauflängenkodierung, etc). Daher "Preprocessing", es ist ein Vorverarbeitungsschritt der redundante Daten durch Nullen ersetzt.

    Vermutlich hatten schon hunderte Leute dieselbe Idee, und was besonderes ist es auch nicht (daher in Off-Topic). Vielleicht kann damit ja trotzdem jemand etwas anfangen :)

    Beispiel mit zwei Datensätzen (oben im Skript via "GetSomeData" und "GetSomeData2") abrufbar. In der Konsole kann beobachtet werden die der Algorithmus "warmläuft", zu Beginn ändert sich fast nichts am Input (da jede Vorhersage daneben liegt), später bestehen die Daten aber zum Großteil aus Nullen (im Redundanten Fall bestehen sie quasi exklusiv aus Nullen). Getestet wurde nur rudimentär.

    AutoIt
    ; Test
    
    Local $sOriginal = GetSomeData() ; Normaler Text ohne wiederholungen
    ;~ Local $sOriginal = GetSomeData2() ; Sehr redundanter Text
    
    Local $v = StringToStruct($sOriginal) ; Um jegliche Encoding Probleme zu umgehen -> Array of Bytes (kennt nur Bytes und sonst nichts)
    Local $b = StructToBin($v)
    
    Local $LUT_Bits = 16 ; Wert zwischen 1 und 16. Bis 8 Bit gehts "schnell" ab 8 Bit wirds langsam (StringLUT = Langsam). Größerer Table = besser (Falls genug Daten vorhanden sind, ab ca. 4KB ist ein 16Bit Table am besten)
    
    Local $c = PredictionEncode($b, $LUT_Bits)
    Stats($c, $LUT_Bits, 'encoded')
    Local $d = PredictionDecode($c, $LUT_Bits)
    Stats($d, $LUT_Bits, 'decoded')
    ConsoleWrite(($d = $b ? '+ OK' : '! FAIL') & @CRLF)
    ConsoleWrite('original:               ' & $b & @CRLF)
    ConsoleWrite('reduced naive entropy:  ' & $c & @CRLF)
    ConsoleWrite('restored naive entropy: ' & $d & @CRLF)
    
    Func Stats($x, $n, $info = '')
    	StringReplace($x, '0', '', 0, 1)
    	Local $zero = @extended
    	StringReplace($x, '1', '', 0, 1)
    	Local $one = @extended
    	ConsoleWrite($info & ' Bits: ' & StringLen($x) & ' LUT-size: ' & StringRight(' ' & $n, 2) & ' #0: ' & $zero &StringFormat(' (%.1f%%)',(100*$zero/($zero+$one))) & ' #1: ' & $one & StringFormat(' (%.1f%%)',(100*$one/($zero+$one))) & @CRLF)
    EndFunc
    
    Func PredictionDecode($sBin, $n = 8)
    	Local $intN = Int(2^$n)
    	Local $_[$intN][2] ; Linearer Lookup für die letzten N bits: [i][0] = Akkumulierte Einsen, [i][1] = Anzahl Gesamt
    	For $i = 0 To $intN - 1 Step 1
    		$_[$i][0] = 0.5 ; 50/50 chance zu Beginn. (da > 0.5 gecheckt wird ist das per default eine Null)
    		$_[$i][1] = 1 ; Initialwert hat das Gewicht von 1. Ansich kann man jede Zahl >0 verwenden, aber 1 war intuitiv
    	Next
    	Local $start = $n + 1, $end = StringLen($sBin)
    	Local $rest = '', $roll = StringLeft($sBin, $n)
    	Local $iLast = '', $pred = '', $right = '', $iLUT = 0
    	If $n <= 8 Then ; Maps für einen schnellen Lookup [11111111] gehen leider nicht bis 16 Bit, also [1111111111111111]
    		Local Static $Int256 = Int256() ; 8Bit Lookup ohne führende Nullen (da Integerkey)
    		For $i = $start To $end Step 1
    			$iLast = Int($roll)
    			$iLUT = $Int256[$iLast]
    			$pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0
    			$right = StringMid($sBin, $i, 1) = '1' ? 1 - $pred : $pred
    			$_[$iLUT][0] += Int($right) ; 0 oder 1
    			$_[$iLUT][1] += 1
    			$rest &= $right
    			$roll = StringTrimLeft($roll, 1) & $right
    		Next
    	Else ; Stringkeys sind wiederum in Ordnung, aber eben langsamer.
    		Local Static $Int65536 = Int65536() ; 16Bit Lookup mit führenden Nullen (da Stringkey)
    		For $i = $start To $end Step 1
    			$sLast = StringRight('0000000000000000' & $roll, 16)
    			$iLUT = $Int65536[$sLast]
    			$pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0
    			$right = StringMid($sBin, $i, 1) = '1' ? 1 - $pred : $pred
    			$_[$iLUT][0] += Int($right) ; 0 oder 1
    			$_[$iLUT][1] += 1
    			$rest &= $right
    			$roll = StringTrimLeft($roll, 1) & $right
    		Next
    	EndIf
    	Return StringLeft($sBin, $n) & $rest
    EndFunc
    
    Func PredictionEncode($sBin, $n = 8)
    	Local $intN = Int(2^$n)
    	Local $_[$intN][2] ; Linearer Lookup für die letzten N bits: [i][0] = Akkumulierte Einsen, [i][1] = Anzahl Gesamt
    	For $i = 0 To $intN - 1 Step 1
    		$_[$i][0] = 0.5 ; 50/50 chance zu Beginn. (da > 0.5 gecheckt wird ist das per default eine Null)
    		$_[$i][1] = 1 ; Initialwert hat das Gewicht von 1. Ansich kann man jede Zahl >0 verwenden, aber 1 war intuitiv
    	Next
    	Local $start = $n + 1, $end = StringLen($sBin)
    	Local $rest = '', $roll = StringLeft($sBin, $n)
    	Local $iLast = '', $pred = '', $right = '', $iLUT = 0
    	If $n <= 8 Then ; Maps für einen schnellen Lookup [11111111] gehen leider nicht bis 16 Bit, also [1111111111111111]
    		Local Static $Int256 = Int256() ; 8Bit Lookup ohne führende Nullen (da Integerkey)
    		For $i = $start To $end Step 1
    			$iLast = Int($roll)
    			$iLUT = $Int256[$iLast]
    			$pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0
    			$right = StringMid($sBin, $i, 1)
    			$_[$iLUT][0] += Int($right) ; 0 oder 1
    			$_[$iLUT][1] += 1
    			$rest &= ($pred = $right) ? 0 : 1
    			$roll = StringTrimLeft($roll, 1) & $right
    		Next
    	Else ; Stringkeys sind wiederum in Ordnung, aber eben langsamer.
    		Local Static $Int65536 = Int65536() ; 16Bit Lookup mit führenden Nullen (da Stringkey)
    		For $i = $start To $end Step 1
    			$sLast = StringRight('0000000000000000' & $roll, 16)
    			$iLUT = $Int65536[$sLast]
    			$pred = ($_[$iLUT][0] / $_[$iLUT][1]) > 0.5 ? 1 : 0
    			$right = StringMid($sBin, $i, 1)
    			$_[$iLUT][0] += Int($right) ; 0 oder 1
    			$_[$iLUT][1] += 1
    			$rest &= ($pred = $right) ? 0 : 1
    			$roll = StringTrimLeft($roll, 1) & $right
    		Next
    	EndIf
    	Return StringLeft($sBin, $n) & $rest
    EndFunc
    
    Func StringToStruct($sString)
    	Local $vString = DllStructCreate('char s[' & StringLen($sString) & ']')
    	$vString.s = $sString
    	Return $vString
    EndFunc
    
    Func StructToString($vString)
    	Local $v = DllStructCreate('char s[' & DllStructGetSize($vString) & ']', DllStructGetPtr($vString))
    	Return $v.s
    EndFunc
    
    Func BinToStruct($sBin)
    	Local Static $Int256 = Int256()
    	Local $vRet = DllStructCreate('byte b[' & Int(StringLen($sBin) / 8) & ']'), $k = 1
    	For $i = 1 To StringLen($sBin) Step 8
    		DllStructSetData($vRet, 1, $Int256[Int(StringMid($sBin, $i, 8))], $k)
    		$k += 1
    	Next
    	Return $vRet
    EndFunc
    
    Func StructToBin($vStruct)
    	Local Static $Bin256 = Bin256()
    	Local $vBytes = DllStructCreate('byte b[' & DllStructGetSize($vStruct) & ']', DllStructGetPtr($vStruct)), $sRet = ''
    	For $i = 1 To DllStructGetSize($vStruct) Step 1
    		$sRet &= $Bin256[$vBytes.b(($i))]
    	Next
    	Return $sRet
    EndFunc
    
    Func Bin256()
    	Local Static $Bin16 = Bin16()
    	Local $Bin256[]
    	For $i = 0 To 255 Step 1
    		$Bin256[$i] = $Bin16[Int($i/16)] & $Bin16[Int($i - Int($i/16) * 16)]
    	Next
    	Return $Bin256
    EndFunc
    
    Func Int256()
    	Local Static $Bin16 = Bin16()
    	Local $Int256[]
    	For $i = 0 To 255 Step 1
    		$Int256[Int($Bin16[Int($i/16)] & $Bin16[Int($i - Int($i/16) * 16)])] = $i
    	Next
    	Return $Int256
    EndFunc
    
    Func Int65536()
    	Local Static $Bin256 = Bin256()
    	Local $Int65536[] ; Ja, Maps sind "langsamer" als Arrays bei sehr vielen Elementen. Ich habe die Zeiten hier nicht gestoppt. Vielleicht gehts schneller, ist aber für dieses Beispiel wurst.
    	For $i = 0 To 65535 Step 1
    		$Int65536[$Bin256[Int($i/256)] & $Bin256[Int($i - Int($i/256) * 256)]] = $i ; StringKeys, da Array Indices hier nicht mehr gehen, da 1111111111111111 ungefähr 2^50
    	Next
    	Return $Int65536
    EndFunc
    
    Func Bin16()
    	Local $Bin16[]
    	$Bin16[0] = '0000'
    	$Bin16[1] = '0001'
    	$Bin16[2] = '0010'
    	$Bin16[3] = '0011'
    	$Bin16[4] = '0100'
    	$Bin16[5] = '0101'
    	$Bin16[6] = '0110'
    	$Bin16[7] = '0111'
    	$Bin16[8] = '1000'
    	$Bin16[9] = '1001'
    	$Bin16[10] = '1010'
    	$Bin16[11] = '1011'
    	$Bin16[12] = '1100'
    	$Bin16[13] = '1101'
    	$Bin16[14] = '1110'
    	$Bin16[15] = '1111'
    	Return $Bin16
    EndFunc
    
    Func GetSomeData()
    	Return 'Ich bin ein Teststring. Hier könnte alles mögliche stehen. Irgendwie muss ich ein paar KB Text voll bekommen... Wie könnte man das anstellen?' & _
    	'Func Int65536()' & _
    	'	Local Static $Bin256 = Bin256()' & _
    	'	Local $Int65536[] ; Ja, Maps sind "langsamer" als Arrays bei sehr vielen Elementen. Es ist aber dennoch schneller als ein Funktionsaufruf oder irgendwelche zusätzlichen Operatoren.' & _
    	'	For $i = 0 To 65535 Step 1' & _
    	'		$Int65536[$Bin256[Int($i/256)] & $Bin256[Int($i - Int($i/256) * 256)]] = $i ; StringKeys, da Array Indices hier nicht mehr gehen, da 1111111111111111 ungefähr 2^50' & _
    	'	Next' & _
    	'	Return $Int65536' & _
    	'EndFunc' & _
    	'Leider lässt die Methode erst bei ziemlich viel Text (ein paar KB) die Muskeln spielen. Für sehr kleine Textmengen sind niedrige LUT Größen besser geeignet, wir wollen hier aber den 16-Bit Table verwenden!' & _
    	'To use this method, one proves that the history of the given process can be recorded in an efficient way, such that the state of the process at any past time can be recovered from the current state and this record, and such that the amount of additional information that is recorded at each step of the process is (on average) less than the amount of new information randomly generated at each step. The resulting growing discrepancy in total information content can never exceed the fixed amount of information in the current state, from which it follows that the process must eventually terminate. This principle can be formalized and made rigorous using Kolmogorov complexity.[3]' & _
    	'Ein bisschen Wikipediatext kann nicht schaden...' & _
    	'An example given by both Fortnow[3] and Tao[4] concerns the Boolean satisfiability problem for Boolean formulas in conjunctive normal form, with uniform clause size. These problems can be parameterized by two numbers (k,t) where k is the number of variables per clause and t is the maximum number of different clauses that any variable can appear in. If the variables are assigned to be true or false randomly, then the event that a clause is unsatisfied happens with probability 2−k and each event is independent of all but r = k(t − 1) other events. It follows from the Lovász local lemma that, if t is small enough to make r < 2k/e (where e is the base of the natural logarithm) then a solution always exists. The following algorithm can be shown using entropy compression to find such a solution when r is smaller by a constant factor than this bound: ' & _
    	'Zeilenumbrüche ignorieren wir mal. Selbstverständlich klappt es damit auch!' & @CRLF & _
    	'Das hier kann super komprimiert werden: ------------------------------------------------------------------------------------------------------- ziemlich cool. 3.141592654' & @CRLF & _
    	'blablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablablabla' & _
    	'Sooo wir sind jetzt bei 22336 Bits angekommen.' & _
    	'Es folgen ein paar Stellen von PI damit "zufällige" Daten vorliegen: 3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 0938446095 5058223172 5359408128 4811174502 8410270193 8521105559 6446229489 5493038196 4428810975 6659334461 2847564823 3786783165 2712019091 4564856692 3460348610 4543266482 1339360726 0249141273 7245870066 0631558817 4881520920 9628292540 9171536436 7892590360 0113305305 4882046652 1384146951 9415116094 3305727036 5759591953 0921861173 8193261179 3105118548 0744623799 6274956735 1885752724 8912279381 8301194912' & _
    	'Ist nicht wirklich zufällig, aber man weiß was ich meine. Der Witz ist jetzt, wenn man die selben Zahlen wiederholt, werden sie fast komplett durch nullen ersetzt, weil genau diese Abfolge ja bereits bekannt ist:' & _
    	'3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647 0938446095 5058223172 5359408128 4811174502 8410270193 8521105559 6446229489 5493038196 4428810975 6659334461 2847564823 3786783165 2712019091 4564856692 3460348610 4543266482 1339360726 0249141273 7245870066 0631558817 4881520920 9628292540 9171536436 7892590360 0113305305 4882046652 1384146951 9415116094 3305727036 5759591953 0921861173 8193261179 3105118548 0744623799 6274956735 1885752724 8912279381 8301194912' & _
    	'Das kann man jetzt im "reduced naive entropy" Stream beobachten :)' & @CRLF & _
    	'Hier noch ein paar Plot-Daten:' & _
    	'# 256 Symbols' & @CRLF & _
    	'128	9.4' & @CRLF & _
    	'256	10.1' & @CRLF & _
    	'512	11.4' & @CRLF & _
    	'1024	11.7' & @CRLF & _
    	'2048	13.3' & @CRLF & _
    	'4096	16' & @CRLF & _
    	'35k Bits sollten zu Demonstrationszwecken ausreichen.' & _
    	'In diesem Beispiel wird die Anzahl der Nullen von 55.9% auf 79.0% erhöht. Damit kann man doch bestimmt irgendwas anfangen (z.B. Lauflängencodierung etc...)'
    EndFunc
    
    Func GetSomeData2()
    	Return 'Zu Demonstrationszwecken bei sehr redundanten daten gibts hier noch ein Beispiel:' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ!"§$%&/()=?' & _
    	'Das sind 44144 Bits und davon sind 97.9% Nullen'
    EndFunc
    Alles anzeigen

    (Edit: Genau das Gleiche habe ich vor Urzeiten schonmal gebastelt (nur viel umständlicher) und den Code nicht mehr gefunden)

    lg

    M

  • Kalkulator mit festen Variablen

    • Mars
    • 2. April 2024 um 15:30

    Es gibt mehrere Möglichkeiten zur UI Gestaltung. Vermutlich ist es am einfachsten das ISN-AutoItStudio zu verwenden, wenn man eine Grafische Benutzeroberfläche haben will (ISN AutoIt Studio). Da ist ein GUI-Editor dabei.

    Wenn man es via Code machen will (und sich schon etwas auskennt) habe ich dafür auch eine UDF: ([UIBB.au3] User Interface mit automatischer Anordnung der Ctrls - Vorschläge / Wünsche / Ideen). Die Beispiele dazu verwenden aber auch sehr viele Variablen wie "$hRightBot" etc. Das wurde dort so gemacht, damit man besser versteht wie die UDF arbeitet.

    Edit: "UDF" = "User Defined Functions". Im AutoIt-Kontext steht der Begriff stellvertretend für "Bibliothek mit ein paar praktischen Funktionen die man via #include verwenden kann".

    lg

    M

  • Kalkulator mit festen Variablen

    • Mars
    • 2. April 2024 um 15:06

    Aufwandseinschätzung (von jemandem der sich mit AutoIt ein wenig auskennt):
    - <15 Minuten (für das was bei dir im Screenshot angezeigt wird)
    - ~1-5h (wenn man ein ordentliches UI haben will, ggf. mit Interaktionsmöglichkeiten wie "Spalte hinzufügen", "Items editieren", "Laden & Speichern", etc.. Aufwand abhängig davon wie viel man haben will)

    Startpunkt sollte sein: Verwende Arrays (oder Maps)

    - Deine Items (also die Tupel aus "Name" und "Preis") -> In ein Array damit.
    - Deine UI-Elemente ("ein" möglicher Lösungsweg) -> Jede Zeile in eine Map mit ['Name'] = LabelFürName, ['Anzahl'] = InputboxFürAnzahl, ['Einzelpreis'] = LabelFürPreis, etc. Dann ein Array (oder Map) für alle Zeilen anlegen, sodass man Zeilen dynamisch hinzufügen und entfernen kann.

    Ich weiß nicht wie versiert du im Programmieren im Allgemeinen bist, aber sehr viele AutoIt-Anfänger geben jedem UI-Element und allen anderen Sachen eigene Variablen (z.B. $LabelItem1Links, $LabelItem2Links, usw) und haben dann 500+ Zeilen an Copy&Paste um eine Tabelle anzuzeigen. Deshalb der Hinweis auf Arrays und Maps :S

    Edit: Ich glaube du bist hier im falschen Forenabschnitt. Vermutlich wolltest du "Hilfe und Unterstützung" ?

    lg

    M

  • Array über Programmdauer hinweg speichern

    • Mars
    • 22. März 2024 um 14:26

    Ich weiß nicht ob dir das hilft, aber vor urzeiten (10 Jahre her) habe ich mal eine UDF geschrieben um Arrays auf die Platte zu schreiben (als einzelner String). Damals war der Map-Datentyp noch sehr experimentell, weshalb er nicht supported wird.

    Ich kann leider keine Garantie dafür geben, dass alles so funktioniert wie es soll, da sich in der langen Zeit wohl irgendwas in der AutoIt-Internen Handhabung von "Binary" geändert hat (musste da eben ein paar Sachen fixen, vermutlich sind aber immernoch irgendwelche Fehler drin).

    Was die UDF macht (bzw. machen soll):

    - Nimm ein beliebiges 1D oder 2D Array (auch verschachtelt) und mache "einen einzigen String" daraus. (Es gibt Optionen dafür um GDI+Bitmaps, oder "Dateien" nicht als Pointer/String, sondern als "Bitmap" oder "Datei" zu interpretieren. In dem Fall werden die Bitmapdaten (mit .png Kompression, also nicht als Rohdaten) bzw. die komplette Datei eingefügt. Damit lässt sich die UDF auch als Container für Bitmaps und Dateien verwenden)

    - Rekonstruiere dieses Array (incl aller Datentypen) wieder aus diesem String. Importierte Dateien werden NICHT automatisch irgendwo niedergeschrieben, sie sind als String im resultierenden Array. Importierte Bitmaps werden automatisch geladen und ein Pointer im Array hinterlegt.

    - Dieser String lässt sich auch auf der Platte speichern (als Datei) und zu jedem späteren Zeitpunkt wieder auslesen.

    Zur Sicherheit empfehle ich folgendes: Wandle dein Array in einen String um, speichere es als temporäre Datei. Lies diese Datei und mache wieder ein Array daraus. Vergleiche die Arrays vollständig. Nur wenn dieser Vergleich erfolgreich war ist das was auf der Platte liegt wirklich "das was du haben willst". Fall nicht -> Irgendwo ist ein bug den du mir gerne mitteilen kannst, dann schaue ich in der UDF und fixe das.

    lg

    M

    Dateien

    ArrayToStringEx_22_03_24.zip 6,15 kB – 404 Downloads
  • Data Collection-Variables / Maps in AutoIt - Status?

    • Mars
    • 19. Februar 2024 um 20:18

    Das liegt daran, weil es für diese Art von Problemen so viele Lösungen gibt :)
    Jetzt haben wir:

    - Verschachtelte Arrays (Indexbasiert)
    - Verschachtelte Maps (Indexbasiert)
    - Verschachtelte Maps (Stringkey basiert)
    - SQLite (DB basiert, ist teil des Standards in AutoIt)
    - JSON (Stringkey basiert, falls man es damit machen möchte, dann geht das auch, da gibts ne gute UDF)
    - Dict (Stringkey basiert, mit BuiltIn Funktionen, oDict)
    - Irgendwo habe ich neulich auch eine Table-UDF (für Tabellen) gesehen. Habe aber vergessen wo.

    lg

    M

  • Data Collection-Variables / Maps in AutoIt - Status?

    • Mars
    • 19. Februar 2024 um 14:37

    Ich bin bei Enums ganz altbacken und verwende Großbuchstaben und Unterstriche (auch wenn ich das im Fließtext nicht gemacht habe) ohne Datentyp (typisch für #Define in C).

    Hier wäre das also sowas wie:
    ...
    $OLIST_WIDTH, _ ; Spaltenindex in der Objektliste (die 2D Map) für das Feld "Breite"
    ...

    Das sieht dann zwar aus wie Code aus den 80ern (obwohl ich da noch nichtmal gelebt habe), ist für mich aber am besten Lesbar. Dann sieht man direkt was Globale Konstanten sind.

    lg

    M

  • Data Collection-Variables / Maps in AutoIt - Status?

    • Mars
    • 19. Februar 2024 um 14:04

    Damit habe ich sowas gemeint wie _ObjectList_AddItem($mmList, $mItem), _ObjectList_GetItemByKey($mmList, $iFuesse), etc. Die üblichen Verdächtigen. Oder DB-Ähnliche Queries wie _ObjectList_GetAllItemsWith($mmList, $iKey, $xValue). (Den prefix 'mm' kann man auch weglassen. Der ist zur Übersicht, dass man nicht vergisst dass "List" eine "Map of Maps" ist. "x" steht für "Unbekannter Typ" und "i" für Integer)

    Noch ein Hinweis zu Maps (der eigentlich offensichtlich ist, aber der hat mich schon einige Nerven beim debuggen gekostet): MapRemove erzeugt Löcher.

    AutoIt
    Local $_[]
    $_[0] = 'Null'
    $_[1] = 'Eins'
    $_[2] = 'Zwei'
    MapRemove($_, 1)
    For $i = 0 To UBound($_) - 1 Step 1 ; Falsch. Wirft aber keinen Error.
    	ConsoleWrite($i & ' ' & $_[$i] & @CRLF)
    Next
    For $i In $_ ; Man hat keinen Index, bekommt aber alle Elemente (Alternative zu MapKeys)
    	ConsoleWrite($i & @CRLF)
    Next
    Alles anzeigen

    lg

    M

  • Data Collection-Variables / Maps in AutoIt - Status?

    • Mars
    • 19. Februar 2024 um 12:03

    Richtige Klassen und richtige Structs gibt es in AutoIt nach wie vor nicht. (DllStructs zählen nicht, die muss man von Hand verschachteln, und wenn man Strings als Datentyp hat muss man immer char[] verwenden was oft etwas nervig ist)

    Maps verwende ich inzwischen quasi exklusiv, wenn es um "kleine Arrays", oder "Fake Klassen" geht. Mein Vorgehen ist dabei eigentlich immer wie folgt:

    AutoIt
    Global Enum $TYPE_VECTOR2
    
    Func Vector2($vx = 0, $vy = 0)
    	Local $_[]
    	$_[0] = $vx
    	$_[1] = $vy
    	$_[99] = $TYPE_VECTOR2
    	Return $_
    EndFunc

    Der Trick ist nun, dass du via Switch $_[99] aussortieren kannst welche "Typen" wie behandelt werden.

    Soweit ich das sehen kann sind Maps inzwischen stabil, haben keine Memory Leaks (zumindest keine die ich noch finden konnte, ich habe selbstverständlich danach gesucht), und zu allem Überfluss sind sie für Integer-Keys in den meisten Fällen schneller als Arrays (bis zu einer gewissen Größe).

    Von daher:
    - Mach dir eine 2D Map (Map of Maps). Die kann man via $Map[][] in 2D auch direkt lesen und schreiben und sie verhält sich bei Integer-Keys exakt wie ein 2D Array. Hat aber den Vorteil dass man Zeilen hinzufügen kann, während man ein Array nicht einfach erweitern kann. Ich persönlich verwende immer Integer-Keys und ein "Global Enum mit $Name, $ID, $Fuesse, $Teileliste" direkt zu Beginn. Maps "kann" man auch mit String-Keys verwenden, aber damit verwirre ich mich meistens eher selbst als dass es was bringt.
    - In die erste Zeile kommen wie üblich die Eigenschaften (Name, ID, Füße, Teileliste, etc)
    - Teilelisten kannst du auch als Map direkt dort ablegen und dann via "$Map[15][$TeileListe][0] = Erstes Teil" lesen und schreiben.
    - Noch ein Vorteil von Integer-Keys (wenn du dich daran hältst sie von 0 an aufsteigend zu verwenden, ohne Lücken): UBound kann verwendet werden statt MapKeys -> Eine Map mit aufsteigenden Integer-Keys kann exakt wie ein Array verwendet werden. (Edit: Das gilt natürlich nicht für "Fake-Klassen" bei denen in der [99] der Typ steht)

    Du müsstest natürlich sämtliche Funktionen dieser "Informationsliste" selbst schreiben. Fast alle davon sollten aber trivial sein.
    Falls deine Objekteliste 10.000+ Einträge hat ist diese Methode vermutlich zu langsam / zu aufwendig. Dann brauchst du vermutlich eine DB und damit kenne ich mich nicht aus :D
    Edit: Genau für diesen Fall hat AspirinJunkie vermutlich eine geeignete UDF.


    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™