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. Andy

Beiträge von Andy

  • vokabeltrainer

    • Andy
    • 12. Oktober 2011 um 00:29

    @derfium,
    der Witz an einer Programmiersprache ist, daß man 1000 Möglichkeiten hat, ein Problem zu lösen.....
    Du könntest dein Script 467 mal hintereinanderkopieren, den Text entsprechend editieren (die Vokabeln) und hättest genau das, was du brauchst in 14359 Programmzeilen!
    Allerdings wäre das Ganze SEHR unübersichtlich, und neue Vokabeln dazuschreiben würde bedeuten, immer den Quelltext ändern zu müssen.....nicht sehr schön.

    Vokabeln und Programm trennen ist deer erste Schritt!
    Also schreibt man zum Beispiel die Vokabeln einfach in eine Datei.
    Mach in Windows den Editor auf, (oder benutze Scite) und schreib einfach die Vokabeln nebeneinander mit Komma getrennt in eine Zeile...also etwa so:

    Code
    hello,Hallo
    car,Auto
    dog,Hund
    cat,Katze


    speichere diese Daten als "Vokabeln.txt" in deinem Programmverzeichnis ab. Nun musst du beim Erweitern dieser "Datenbank" nur noch diese Datei öffnen und nicht mehr deinen Quellcode verändern.
    Ausserdem hast du nun die Möglichkeit, sowohl von Englisch nach Deutsch als auch von Deutsch nach Englisch abgefragt zu werden.^^

    Dazu musst du in deinem Programm nur die Datei öffnen, deine Vokabeln auslesen (vor dem Komma steht das deutsche Wort, hinter dem Komma das englische) und zufällig eine Vokabel auswählen und die passende Übersetzung dazu abfragen.
    Fehlen nur noch die passenden bzw. fehlenden Programmfunktionen^^
    In der deutschen Hilfe zu AutoIt solltest du fündig werden, dort sind für alle Funktionen Beispielscripte enthalten, die mit einem Mausklick ausgeführt werden können.
    Ich würde (als Anfänger) mit fileread() den Dateiinhalt in eine (String-)Variable einlesen, die Anzahl der im String enthaltenen Kommas bestimmen (damit hast du automatisch die Anzahl der Vokabeln) und dann per Random(1,$Anzahl_Kommas,1) eine Zeile der Datei auswählen.
    Das Wort links vom Komma ist das englische, rechts vom Komma das deutsche.
    Das gesamte Programm sollte bequem in 10 Zeilen passen und nur die rudimentären String- und Dateibearbeitungsfunktionen benutzen.

    Eine große Hilfe für Anfanger ist die Darstellung der Inhalte der Variablen während der Programmentwicklung
    Die DEBUG-Messageboxen in Scite zur Anzeige der Variableninhalte erhält man, wenn man den Cursor auf die zu untersuchende Variable setzt und STRG+SHIFT+D drückt. (siehe Menü 'Extras' )
    Alle DEBUG-Messagebogen auskommentieren kann man mit STRG+ALT+D
    Alle DEBUG-Zeilen löschen kann man mit STRG+ALT+Z

    Beispiel:

    Spoiler anzeigen
    [autoit]

    ;Wenn vokabeln.txt noch nicht besteht, anlegen
    if not fileexists("vokabeln.txt") then FileWrite("vokabeln.txt","hello,Hallo"&@crlf&"car,Auto"&@crlf&"dog,Hund"&@crlf&"cat,Katze"&@crlf)

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

    ;;editor öffnen, Daten können eingetragen werden, SPEICHERN nicht vergessen^^
    shellexecute("vokabeln.txt")

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

    ;Hier gehts los....
    ;Dateiinhalt in Stringvariable einlesen
    $string=fileread("vokabeln.txt")
    if @error then;falls Fehler aufgetreten sind....
    MsgBox(0,"Fehler Vokabeldatei!","Programm wird beendet! Bitte eine Datei Vokabel.txt erstellen und mit Komma getrennte Vokabelpaare eintragen!")
    exit;Ende
    endif
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$string' & @lf & @lf & 'Return:' & @lf & $string) ;### Debug MSGBOX

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

    ;Anzahl Kommas im String bestimmen
    StringReplace($string,",",",") ;komma mit komma im String ersetzen
    $AnzahlKommas=@extended ;anzahl ersetzter kommas ausgeben
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$Anzahl_Kommas' & @lf & @lf & 'Return:' & @lf & $AnzahlKommas) ;### Debug MSGBOX

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

    ;Zufallszahl bestimmen zwischen 1 und AnzahlKommas
    $Zufallszahl=random(1,$AnzahlKommas,1)
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$Zufallszahl' & @lf & @lf & 'Return:' & @lf & $Zufallszahl) ;### Debug MSGBOX

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

    ;Zufällige Zeile aus Datei auslesen
    $Zufallszeile=FileReadLine("vokabeln.txt",$Zufallszahl)
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$Zufallszeile' & @lf & @lf & 'Return:' & @lf & $Zufallszeile) ;### Debug MSGBOX

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

    ;Position des Kommas in der Zeile bestimmen
    $Kommaposition=stringinstr($Zufallszeile,",")
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$Kommaposition' & @lf & @lf & 'Return:' & @lf & $Kommaposition) ;### Debug MSGBOX

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

    ;linker Teil vom Komma ist die englische Vokabel
    $EnglischeVokabel=stringleft($zufallszeile,$kommaposition-1)
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$EnglischeVokabel' & @lf & @lf & 'Return:' & @lf & $EnglischeVokabel) ;### Debug MSGBOX

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

    ;rechter Teil vom Komma ist die deutsche Vokabel
    $DeutscheVokabel=stringtrimleft($zufallszeile,$kommaposition);linker Teil incl Komma wird abgeschnitten
    MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$DeutscheVokabel' & @lf & @lf & 'Return:' & @lf & $DeutscheVokabel) ;### Debug MSGBOX

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

    ;jetzt kommt dein Programmteil^^
    $AbgefragteVokabel = InputBox ("Hallo" , "Was heißt '"&$DeutscheVokabel&"' auf englisch?")
    If $AbgefragteVokabel = $EnglischeVokabel Then
    MsgBox (0, "Richtig! ", "Gut gemacht! ")
    Else
    MsgBox (0, "Falsch! ", "Das war leider falsch. Die englische Übersetzung von '"&$DeutscheVokabel&"' ist '"&$EnglischeVokabel&"'")
    endif

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

    $AbgefragteVokabel = InputBox ("Hallo" , "Was heißt '"&$EnglischeVokabel&"' auf deutsch?")
    If $AbgefragteVokabel = $DeutscheVokabel Then
    MsgBox (0, "Richtig! ", "Gut gemacht! ")
    Else
    MsgBox (0, "Falsch! ", "Das war leider falsch. Die deutsche Übersetzung von '"&$EnglischeVokabel&"' ist '"&$DeutscheVokabel&"'")
    endif

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Prozedurale Grafiken

    • Andy
    • 11. Oktober 2011 um 21:10

    Was soll ich sagen.....wieder mal ein echter Marsi! :thumbup:
    Sehr fein, klasse Idee, TOP umgesetzt!

    Aber wie UEZ schon sagte, brotlose Kunst (TROTZDEM ist es eine KUNST!).
    Aber es macht Spass :D , ansonsten ist es doch auch langweilig, wenn man keine Herausforderung hat^^

  • progandy hat Geburtstag!

    • Andy
    • 11. Oktober 2011 um 20:58

    Glücklichen Herzwunsch und alles Gute, Namensvetter!

    Schön zu sehen, daß es "jüngere" Leute gibt die RICHTIG was auf dem Kasten haben. Vielen Dank für deine tollen Beiträge, hau weiter rein und lass es krachen :thumbup:

  • [Spiel] PanzerFight

    • Andy
    • 26. September 2011 um 22:41

    Hi,
    mach das online spielbar mit bis zu 10 spielern gleichzeitig und es wird ein knaller :thumbup:

  • DeskStream 2 Release Candidate 1.8

    • Andy
    • 24. September 2011 um 18:27

    Steuerung ist in Ansätzen möglich, ich wurstele gerade an einer Impelmentierung von OpenCl (nicht Gl) in AutoIt, damit kann man die Datenkompression auf einer geeigneten Graka laufen lassen, das sollte die übertragenen Datenmengen nochmal reduzieren und somit schnellere Bildraten bringen....lasst euch überraschen...

  • Suche Heimkinosystem 5.1

    • Andy
    • 27. August 2011 um 10:57

    Hi,
    netter Thread, das Thema steht bei mir spätestens Weihnachten auch an....
    Bei meiner "alten" (ca. 6-8 Jahre alten Anlage) hab ich auf einen befreundeten audiophilen Freak gehört, bin in ein Fachgeschäft rein, hab 3-4 meiner 5.1-fähigen DVD´s in einen Player gestopft und mir diverse Player/Receiver/Lautsprecher-Kombinationen angehört.

    Das mit den angebotenen 546 verschiedenen Klangpresets (DSP´s) hatte sich dann auch schnell erledigt, 98% davon klingen definitiv sch***, das deckt sich also hiermit :D :

    Zitat

    Eigentlich sind das aber nur "Marketing-Sprüche" (beim Samsung Produkt) für diverse DSP's.
    Der Nutzen von diesen Klangprogrammen ist eher fraglich und ein gern diskutiertes Thema bei den Heimkinofans - mir persönlich gefällt das nicht.

    Die Lautsprecher waren auch schnell gefunden, 2 Regalboxen, Center und 2 kleine Satelliten. Für das von mir bezahlte Geld hatte ich eine Kombination bekommen, die sich für MICH am besten angehört hat. Der Yamaha-Player war jeden Cent wert, leider ist er schon nach kurzer Zeit verstorben...

    Btw. wie unterschiedlich das persönliche Gehör ist, hatte ich mit meinen Kumpels ausprobiert, die Sound-Ausgabe des Players wurde einmal auf mein <600€ System ausgegeben, und einmal auf der >5000€ Anlage meines Freundes. "Fetter" war der Sound bei meinem Kumpel, aber mein Gehör ist eher auf die Höhen ausgerichtet, es gab also 2 völlig unterschiedliche "Sounds". Welcher jetzt aber "besser" zum Film gepasst hat, war nach 3 Bier sowieso egal^^. Und das geknurpsel der Kartoffel-Chips tut sein übriges....

  • 2D Array durchsuchen, _ArraySearch() zu langsam :(

    • Andy
    • 27. August 2011 um 10:21

    Hi,
    um spezielle Geschwindigkeitsprobleme zu lösen ist es meist sinnvoll, nicht auf allgemeine Funktionen ( z.B. _arraysearch() )zurückzugreifen, sondern eine eigene Funktion zu schreiben...

    Mach dir einfach mal bewußt, was dein Programm macht:
    Erstelle eine Liste mit x-tausend Einträgen von gespeicherten Prozessnamen.
    Erstelle eine Liste mit y-hundert laufenden Prozessen.
    Vergleiche JEDEN gespeicherten Eintrag x mit JEDEM laufenden Prozess y....
    Das ist sehr ineffektiv!

    Im Prinzip soll doch der laufende Prozess anhand seines Namens in der Suchliste gefunden werden.
    Das erinnert mich z.B. daran, ein Wort in einem Wörterbuch oder Lexikon zu finden. (Ja, das ist der grosse Mist am Internet, die einfachsten Sachen wie die Benutzung von Lexika werden verlernt)
    Wenn ich in einem Lexikon das Wort "Prozess" suche, dann fange ich bestimmt nicht auf der ersten Seite bei "A" an und blättere solange weiter, bis ich beim Anfangsbuchstaben "P" angelangt bin^^, sondern schlage das Kapitel "P" direkt auf.
    Bzw. schlage ich sogar im Kapitel "P" relativ weit hinten nach, weil der 2. Buchstabe von "Prozess" ein "r" ist, und der im Alphabet weit hinten steht.
    Wenn das Lexikon 3999 Seiten hat, "kostet" meine Suchanfrage höchstens 3-4 Seiten blättern 8o , während du im schlimmsten Fall ALLE 3999 (in deinem Fall unsortierte) Seiten durchsuchen musst :huh:

    In AutoIt gibts eine sehr schnelle Methode solche Listen zu durchsuchen, AspirinJunkie hat HIER einige Alternativen vorgestellt.

    Wenn das umkopieren der Prozesse (Array aus Processlist() ) in die Liste zu lange dauert oder du nur mit arrays arbeiten willst, erstelle ein sortiertes Array deiner gespeicherten Prozessnamen und merke dir die Indizes (und die Anzahl) der Prozessnamen mit den Anfangsbuchstaben aus dem Alphabet.
    Pseudocode:

    Code
    $a=_index(AnfangsbuchstabeProzessname)
    $b=_index(AnfangsbuchstabeProzessname)+_anzahl(Prozessnamen_mit_diesem_Anfangsbuchstaben) 
    For $i=$a to $b  ;durchsucht nur die Einträge mit gleichem Anfangsbuchstaben
    if $exefilename=$aProclist[$i] then _gefunden()
    next
  • verschiedene befehle bei google und in der sufo nicht gefunden. bitte hilfe

    • Andy
    • 30. Juli 2011 um 08:29

    Hi,
    AutoIt ohne deutsche Hilfe....lernst du Schwimmen ohne Wasser?

    Die Hilfe in AutoIt (und in den meisten anderen Programmen) besteht nicht nur aus F1!
    Wirksame Suchtechniken bestehen aus mehr, als irgendwelche Wörter in Google einzutippern und nach einem "Enter" drauf zu hoffen, dass auf der ersten Seite der Treffer etwas nützliches steht.

    In der AutoIt-Hilfe benutze ich idR den Reiter "Suchen".
    Dieses Fenster beinhaltet mehrere wichtige Hilfsmittel, um die Suche einzugrenzen.

    Zunächst mal die Eingabezeile:
    Dort wird der Suchbegriff reingeschrieben. Ich persönlich verwende diese Zeile meistens nur in Kombination mit dem *- Zeichen, welches als Platzhalter für mehrere Buchstaben verwendet werden kann, während das ?-Zeichen als Platzhalter für einen Buchstaben gilt. Dazu später mehr.
    Wenn man auf den kleinen Button rechts in der Eingabezeile drückt, bekommt man die letzten Suchanfragen in einer Dropdown-Liste.
    Rechts daneben befindet sich ein kleiner Button mit einem Pfeil nach rechts, dort draufgeklickt erhält man die möglichen logischen Verknüpfungen (AND OR NEAR NOT) , mit welchen die Suchbegriffe kombiniert werden können.

    Unterhalb der Eingabezeile befinden sich zwei Buttons, Themen auflisten wertet die Suchanfrage aus und entspricht dem ENTER nach dem Eintippen der Suchbegriffe in die Eingabezeile. Nach erfolgreicher Suche werden die Suchergebnisse aufgelistet, oder es erscheint ein kleines Fenster, mit der Info "Keine Themen gefunden". Dann muss man seine Suchanfrage etwas erweitern.
    Mit dem Anzeigen-Button werden die in der Trefferliste markierten Suchergebnisse im rechten Fensterteil angezeigt. Ein Doppelklick auf einen Treffer in der Liste führt zum gleichen Ergebnis.

    Unterhalb des Listenfeldes für die gefundenen Treffer befinden sich 3 Checkboxen.
    Vorherige Ergebnisse suchen habe ich ehrlich gesagt noch nie benutzt :whistling:
    Ähnliche Wörter suchen ist bei mir eigentlich immer aktiv.
    Wichtig ist Nur Titel suchen, da beim Aktivieren dieser Checkbox nicht im gesamten Text gesucht wird. Sehr nützlich, wenn man Funktionen bzw. Befehle sucht. Allerdings sollte man diese Checkbox im Auge behalten, ist sie angehakt, werden die angezeigten Treffer extrem eingeschränkt. Für den Anfänger ist es sicherlich sinnvoll, diesen Haken in der Checkbox zu entfernen!


    Beispiel: Ich suche Funktionen, mit denen ich in meinen mit AutoIt erstellten Fenstern Aktionen mit der Maustaste abfragen kann.
    Also einfach mal Maustaste in die Suchzeile eintragen und nach einem Enter findet die Suche....SEHR viele Ergebnisse.
    Wenn man nach Maustaste abfragen sucht, reduzieren sich die Ergebnisse gewaltig.
    Da AutoIt auf der englischen Sprache basiert, könnte man einfach mal nach mouse suchen. Aber wieso gibt es hier keine Treffer, obwohl man doch in den vorherigen Suchabfragen in der Liste mehrere Treffer mit dem Inhalt mouse angezeigt bekam? Die Suchfunktion sucht zunächst nach GENAU der Entsprechung, die eingegeben ist. Wenn man nun nach Begriffen suchen möchte, in denen das Suchwort enthalten ist, muss man das mit dem Suchbegriff kenntlich machen.
    Dafür verwende ich ausschliesslich das *-Zeichen, welches als Platzhalter für beliebig viele Buchstaben steht. Man kann das *-Zeichen an jeder Position im Suchbegriff verwenden.
    mouse* findet also alle Wörter, welche mit mouse anfangen.
    *mouse findet alle Wörter, welche mit mouse enden.
    *mouse* findet also alle Wörter, welche mit mouse zu tun haben. Einfach eintippen, und man erhält eine Liste sämtlicher Hilfeseiten, die irgendwo mouse enthalten. Diese Liste ist aber noch etwas groß, eigendlich suchen wir ja nur nach Funktionen, welche mit der Maus zu tun haben.

    Dafür benutzt man den Haken in der Checkbox Nur Titel suchen. Die Liste wird nun gefiltert nach Ergebnissen, welche mouse im Titel haben. Das sind größtenteils die AutoItbefehle bzw. -funktionen.

    Wenn ich suche, benutze ich generell den Suchbegriff nur mit vorangestelltem und nachfolgendem *-Zeichen!
    Das findet bei der Suche nach *random* nämlich auch die Funktion SRandom().
    Zu fast jeder Funktion existieren unter dem Beschreibungstext Beispielscripte, ein einfacher klick auf den Button "Dieses Script öffnen" befördert das Beispiel in den Scite-Editor!


    Per google habe ich schon seit Jahren nicht mehr "von Hand" gesucht, jedenfalls nicht im Zusammenhang mit AutoIt. Dazu verwende ich ErGo, die erweiterte Googlesuche (bissl Eigenwerbung muss ja sein^^).
    Übrigens ersetze ich auch die Forensuche damit.
    "Zu Fuss" kann man das natürlich auch, aber um z.B. im englischen und im deutschen Forum gleichzeitig nach Beiträgen zum Thema "random" zu suchen müsste man
    g site:autoit.de random in die Eingabezeile des Browsers tippen, einen neuen Tab erstellen und dort g site:autoitscript.com random eingeben....das geht per ErGo wesentlich effektiver.

  • [Spiel] TetrisInvaders für 2 Personen

    • Andy
    • 24. Juli 2011 um 16:55

    Extrem cremig!

    Ich spiele gerade mit meiner Tochter zusammen, wir sind Level 20 :thumbup:
    Das Spiel ist dermassen klasse, das hat einen tollen Sound verdient!

    Weiterhin wäre nice:
    Bosslevel (alle 10 Runden) mit schiessenden Gegnern.
    Seitwärts fliegende Schiffe für Bonuspunkte.
    Sich drehende Tetrissteine....uvm... 8o
    GALAGA-Modus :rock:
    /EDIT/
    Doppelte und dreifache Kanone! MEHR TETRISSTEINE !


    Das Game hat definitiv Suchtfaktor (für 2) und ENDLICH kann man mal wieder wie blöde auf den Tasten rumkloppen^^

  • AutoIt und die Zufallszahlen

    • Andy
    • 24. Juli 2011 um 09:39

    Hi,
    wie AspirinJunkie schon erklärt hatte, bestehen natürlich mathematische Grundlagen (Stochastik) im Zusammenhang mit der "Zufallszahlen"-Spielerei.

    Im Endeffekt ist es einfach:
    Erzeuge n "zufällige" Zahlen und verifiziere mit diversen Verfahren, ob die Verteilung auch wirklich zufällig sein könnte.
    In einem bestimmten Bereich (chi² wurde angesprochen) sind Abweichungen als normal (bzw. systemimmanent) zu betrachten.

    Für den vorliegenden Fall der grafischen Spielerei sieht das so aus, daß nach etlichen aufeinanderfolgenden Versuchen irgendwann der Fall eintritt, daß der "Pixelgänger" vom Mittelpunkt der GUI auf einer geraden Linie zum Rand läuft...mathematisch kein Thema, denn dieser Fall muss von einem "echten" Zufallszahlenalgorithmus natürlich auch vorgesehen werden.
    Wenn dieser Fall nach den (berechneten) 12^345 Versuchen 3x nacheinander auftritt, dann sind die Mathematiker natürlich stolz! Wenn dieser Fall allerdings nach dem 2. Versuch auftritt, dann stellt wohl jeder die "Zufälligkeit" in Frage ;)

    Anders gesagt, "Zufall" wird nur dort als solcher akzeptiert, wo Chaos erwartet wird.
    Wären bei den ersten Ziehungen der Lottozahlen an 3 Samstagen nacheinander die Zahlen 1,2,3,4,5,6 gezogen worden, hätte es mit Sicherheit einige böse Verwicklungen gegeben, und niemand würde heute Kreuzchen in kleine Kästchen machen....und kein Richter und Staatsanwalt hätte die "Wahrscheinlichkeit" für diesen Fall akzeptiert!

  • 2 Hexwerte überprüfen, dann Aktion

    • Andy
    • 23. Juli 2011 um 17:40
    Zitat von John

    Die Hilfe sagt, 0 = Überlauf


    die Hilfe sagt auch:

    Zitat von Hilfe

    Die Funktion funktioniert nur mit Zahlen die in einen 32-bit-Integer passen (-2147483648 bis 2147483647)

  • AutoIt und die Zufallszahlen

    • Andy
    • 23. Juli 2011 um 14:44
    Zitat

    Ob du das Bild nun malst oder einfach nur die Anzahl der Vorkommen von Rechts-und-Links-Schritten vergleichst ist da egal wenn du das auf Zufälligkeit hin untersuchen willst.

    richtig, und weitergedacht kommt man auf so etwas: http://www.pixelmonkeys.org/

  • AutoIt und die Zufallszahlen

    • Andy
    • 23. Juli 2011 um 14:13
    Zitat

    Du schließt mehr oder weniger daraus, dass irgendwann ein Rand erreicht wird (was eigentlich im Unendlichen bei jeder Gui-Größe sein müsste) das es sich nicht um einen "echten" Zufall handelt?

    Genau DAS ist das Problem^^
    Die Wahrscheinlichkeit, daß selbst bei unendlicher GUI-Größe der Rand erreicht wird, ist genauso groß wie die Wahrscheinlichkeit, daß bei einer GUI-Größe von 10x10 Pixeln der Rand NICHT erreicht wird!

  • AutoIt und die Zufallszahlen

    • Andy
    • 23. Juli 2011 um 14:09

    bei 1000x1000 läuft´s schon länger....
    Wenn der Rand erreicht wurde, startet das Script wieder in der Mitte.....

    Spoiler anzeigen
    [autoit]


    #include <gdiplus.au3>

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

    _GDIPlus_Startup()
    $width = 1000
    $height = 1000

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

    $hgui = GUICreate("Random Viewer", $width, $height)
    GUISetState()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hgui)
    $hPen = _GDIPlus_PenCreate()

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

    ;~ Dim $a[$width + 2]
    ;~ $max = 0
    ;~ While $a[$max] < $height
    ;~ $random = Random(1, $width, 1)
    ;~ _GDIPlus_GraphicsDrawLine($hGraphic, $random, $a[$random], $random, $a[$random] + 1, $hPen)
    ;~ $a[$random] += 1
    ;~ If $a[$random] > $max Then $max = $random
    ;~ WEnd

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

    ;~ MsgBox(0, "häufigste Zahl zwischen 1 und " & $width, $max)

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

    _GDIPlus_GraphicsClear($hGraphic)
    $anz=0
    While $anz<>100
    $anz+=1
    $x = Int($width / 2) ;startpunkt mitte
    $y = Int($height / 2)
    Do
    $random = Random(1, 4, 1)
    Switch $random
    Case 1 ;rechts
    $x += 1
    $col = 0xFF0000FF
    Case 2 ;links
    $x -= 1
    $col = 0xFF00FF00
    Case 3 ;oben
    $y -= 1
    $col = 0xFFFF0000
    Case 4 ;unten
    $y += 1
    $col = 0xFF000000
    EndSwitch
    $hPen = _GDIPlus_PenCreate($col)
    _GDIPlus_GraphicsDrawLine($hGraphic, $x, $y, $x, $y + 1, $hPen)
    Until $x < 0 Or $x > $width Or $y < 0 Or $y > $height ;ende, wenn rand erreicht
    WEnd
    MsgBox(0, "", "Ende")

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit]
  • AutoIt und die Zufallszahlen

    • Andy
    • 23. Juli 2011 um 13:49
    Zitat

    Nur in diesem Beispiel ist es so das die Tatsache allein das es den Rand erreicht noch kein Hinweis auf nichtzufällige Verteilung ist.

    Richtig, daher die Frage wie groß die GUI sein müsste, damit der Rand nicht erreicht wird....
    Oder wird "irgendwann" immer der Rand erreicht? Was natürlich die Frage aufwirft, wieso gerade DIESER Rand erreicht wurde und nicht einer der 3 anderen :pinch:

  • AutoIt und die Zufallszahlen

    • Andy
    • 23. Juli 2011 um 12:57

    Moinz!

    Um einem Computerneuling zu demonstrieren, dass bei einem Computer Zufall!=Zufall ist (jedenfalls in "kurzen" Schleifen), habe ich folgendes Miniscript geschrieben.

    Im ersten Teil werden einfach Zufallszahlen zwischen 1 und der Breite der GUI erzeugt und grafisch als Länge eines Balkens dargestellt. Ist der untere Rand der GUI erreicht, wird die häufigste Zufallszahl ausgegeben.

    Beim zweiten Teil startet das Script in der Mitte der GUI und wendet sich, je nach dem Ergebnis der Random-Funktion zwischen 1 und 4 einer Himmelsrichtung zu und markiert das dortige Pixel mit einer Farbe. Wird der Rand der GUI erreicht, wird das Script beendet.
    Die Frage lautet: Ab welcher Größe der quadratischen GUI läuft der Algorithmus unendlich lange? :D

    Spoiler anzeigen
    [autoit]


    #include <gdiplus.au3>

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

    _GDIPlus_Startup()
    $width = 500
    $height = 500

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

    $hgui = GUICreate("Random Viewer", $width, $height)
    GUISetState()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hgui)
    $hPen = _GDIPlus_PenCreate()

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

    Dim $a[$width + 2]
    $max = 0
    While $a[$max] < $height
    $random = Random(1, $width, 1)
    _GDIPlus_GraphicsDrawLine($hGraphic, $random, $a[$random], $random, $a[$random] + 1, $hPen)
    $a[$random] += 1
    If $a[$random] > $max Then $max = $random
    WEnd

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

    MsgBox(0, "häufigste Zahl zwischen 1 und " & $width, $max)

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

    _GDIPlus_GraphicsClear($hGraphic)
    $x = Int($width / 2) ;startpunkt mitte
    $y = Int($height / 2)
    Do
    $random = Random(1, 4, 1)
    Switch $random
    Case 1 ;rechts
    $x += 1
    $col = 0xFF0000FF
    Case 2 ;links
    $x -= 1
    $col = 0xFF00FF00
    Case 3 ;oben
    $y -= 1
    $col = 0xFFFF0000
    Case 4 ;unten
    $y += 1
    $col = 0xFF000000
    EndSwitch
    $hPen = _GDIPlus_PenCreate($col)
    _GDIPlus_GraphicsDrawLine($hGraphic, $x, $y, $x, $y + 1, $hPen)
    Until $x < 0 Or $x > $width Or $y < 0 Or $y > $height ;ende, wenn rand erreicht

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

    MsgBox(0, "", "Ende")

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Geschwindigkeitsvergleich C, Basic, Pascal Unerwartetes Ergebnis?!

    • Andy
    • 17. Juli 2011 um 15:20

    Hi,
    die neuen Prozessoren haben es in sich! Durch die massiven Paralellisierungsmöglichkeiten und die Aufteilung in verschiedene Rechenwerke und Pipelines wird es für die Compiler(bauer) immer schwerer.
    Für den Assemblerprogrammierer wird es fast unmöglich, die Compiler zu schlagen! Bissl was geht immer, aber um welchen Preis?

    Nach ausstoppen des "inner loop" bei der ASM-dll hatte ich festgestellt, daß der Prozessor dort wahnsinnig viel Zeit verbringt. Den "Fehler" konnte ich erst nicht lokalisieren, die reinen Latenzzeiten der SSE-Befehle hätten zu einer Dauer von ca. 30-40 Takten für die Berechnungen (immerhin ~200 Additionen/Subtraktionen und 40 Multiplikationen pro Schleifendurchgang) führen sollen.
    Mitten im Code hatte der Prozessor aber plötzlich 300 Takte lang andere Arbeit, nur welche? Das Geheimnis lag in der Abhängigkeit von Befehlen voneinander, im Endeffekt hatte der Prozessor meinen dilettantischen Code immer wieder umsortiert, um die parallelen Ausführungseinheiten besser auszunutzen....und das mitten im Schleifendurchlauf....

    Ich versuch(t)e bisher immer, die Speicherzugriffe zu minimieren, und alle Berechnungen mit den Prozessorregistern zu machen.
    Viel wichtiger als einige verbummelte Wartetakte infolge Cachemiss (Speicherzugriff) ist aber bei den neuen Prozessoren, die Befehle so in eine Reihenfolge zu bringen, daß die Recheneinheiten parallel zueinander arbeiten können ohne gegenseitig auf Ergebnisse zu warten.
    Das führt nun zur paradoxen Situation, daß ein längeres Programm teilweise wesentlich schneller ausgeführt werden kann!
    Am günstigten ist es natürlich, wenige Befehle (die dann auch noch bestenfalls in eine Instruction-Cacheline passen) zu verwenden, die parallel abgearbeitet werden können.
    Der vorliegende Algorithmus ist dafür denkbar schlecht geeignet, da zwangsläufig in der Berechnung von z.B.

    [autoit]

    Return ($V3 + $t * ($V2 + $t * $V1)) * $t + $V4

    [/autoit]

    Abhängigkeiten auftreten, die nicht parallel ausgeführt werden können. Was das "kostet" kann man sich vorsstellen wenn man weiß, daß der Prozessor im Idealfall 4-16 Additionen und 4-16 Multiplikationen in einem Takt ausführen kann.

    Bei einem Algorithmus, der die paralelle Verarbeitung von Daten nicht hergibt, nützen auch die besten Möglichkeiten des Prozessors nichts!

    Der VC++-Compiler hat nur deshalb im Verhältnis zum SSE-Code so "gut" abgeschitten, weil der Algorithmus nicht gut zu parallelisieren ist! ;) Da machen dann die "langsamen" vom Compiler verwendeten oldschool-FPU-Befehle den Kohl auch nicht fett. Jedenfalls hat der Compiler einige Tricks eingesetzt um bissl Speed rauszuholen!

    Ich habe aber meine Hausaufgaben gemacht und mal die SSE-Befehle etwas umgeordnet, das führt nun zu "nur" 3-facher Geschwindigkeit gegenüber dem Compilercode. Bissl was geht also immer 8o


    Es reicht eben nicht mehr irgendwelchen Code zu tippern und der Compiler/Assembler macht aus Sch*** dann Gold! Das gilt sowohl für C(++) Programmierer, als auch für Assemblerfreaks!

  • Geschwindigkeitsvergleich C, Basic, Pascal Unerwartetes Ergebnis?!

    • Andy
    • 16. Juli 2011 um 11:31

    huhu AspirinJunkie,
    habe jetzt auch mal mehrere Durchläufe gefahren und bin (bis auf c++) ca. beim Faktor 6-8 rausgekommen, das deckt sich auch mit deinen Ergebnissen. Dazu später mehr^^

    Hab die asm-dll jetzt so modifiziert, dass im "inner loop" (die _b()-Funktion) nicht mehr auf Speicher zugegriffen wird. Allerdings beschleunigt das entgegen meiner Annahme nur minimal, da die Zugriffe auf die Struct (im Ram) vom Prozessor schon so gut gecached werden, daß nur der erste Zugriff auf eine Speicheradresse ca. 10 Takte braucht, jeder weitere Zugriff wird in EINEM Takt erledigt (aus dem dann im L1-Cache stehenden Speicherbereich). Da machen natürlich auch die parallen Pipelines was aus, du hattest es ja angesprochen. Wenn parallel gearbeitet werden kann, "fluppt" es einfach^^

    Leider ist der loop so kurz, dass auch ein prefetch (frühes laden vom Speicher in den L1-Cache) nichts bringt. Ich müsste den loop "unrollen" (übrigens macht der VC++Compiler das in deiner dll!), das würde aber wieder Programmieraufwand bedeuten aber ggf bis zu 50% rausholen.

    Was extrem reinhaut sind zeitlich "lange" Durchläufe, d.h. > einigen Millisekunden.
    Ich bin sicher, der windowsinterne Thread(Task)manager schaltet dann zwischenzeitlich auf andere Threads um, das merkt man besonders deutlich bei den dll´s von Lazarus und Pascal, welche den "Umweg" über das Abfangen von Exceptions nehmen. Da braucht bei einem gleichzeitigen Plattenzugriff die dll 5x so lange!
    Autoit blutet dadurch Laufzeitbedingt natürlich am meisten!

    Ich könnte auch anhand deiner Ergebnisse schwören, dass du einen Intel-Prozessor hast ;)
    Weniger an den guten Ergebnissen der Compiler-dlls, als an den "schlechten" vom asm-SSE. Ein unaligned Zugriff auf eine Speicheradresse kostet bei einem Intel-Dual-core oder Sandy-bridge Prozessor 3-8 Takte, während ein alter AMD-Prozessor das in 2 Takten abwatscht. Bei vielen unaligned Speicherzugriffen (der Algorithmus ist einfach besch*** von mir umgesetzt^^) läppert sich das natürlich.

    Zitat

    Das heißt SSE-Code + Threading + Plattformunabhängigkeit!
    Wär das nicht ein Anreiz für dich dich doch ein klein wenig mehr mit den Hochsprachen anzufreunden...?

    habs immer gesagt, JAVA ftw! Da fällt das ganze rumgeeiere im Speicher weg und das Programm läuft auch auf einer Armbanduhr oder einem Mixer!
    Bzgl. optimieren von C++-Code habe ich schon einige extrem gute Artikel von Agner Fog gelesen. Einige passend zum Code eingestreute _mm_*****-Funktionen und der Compiler setzt den C++-code perfekt in SSE um, eine 32x32 Matrixmultiplikation ist dann in C++ genauso schnell wie (wesentlich unproduktiverer) handgeschriebener Assemblercode.

    Aber ich bleibe dabei, in 99,99% aller Fälle bringt Assembler nix, aber beim echten Numbercrunchen und Code der sich fürs Handoptimieren eignet, ist ein schnellerer "inner loop" meistens machbar ;)

    2,7Mhz AMD 4850e (K8, 45Watt TDP 8o)

    Code
    > AutoIt: 6199.06
    > FreeBasic: 9.4
    > Lazarus: 8.93
    > FreePascal: 12.38
    > DevC: 6.84
    > MinGW: 7.17
    > Visual C++: 2.44
    > Assembler: 1.37
  • Geschwindigkeitsvergleich C, Basic, Pascal Unerwartetes Ergebnis?!

    • Andy
    • 10. Juli 2011 um 16:06

    Hi,
    gebe jetzt mal meinen Senf dazu:

    AspirinJunkie
    ich gebe dir in so gut wie allen Punkten Recht, besonders die Punkte "Produktivität" und "Parallelisierung" sind weitab jeglicher Diskussionsgrundlage.
    Da Programmierer heute derart billig sind, kommt es nicht mehr auf die Geschwindigkeit oder Größe des Codes (Programmes) an, sondern nur noch auf die Kosten der Codeerstellung. Time is cash.

    Bei einem "lahmarschigen" Programm (aus welchen Gründen auch immer) wird bei Kundenreklamation einfach auf einen Prozessor der nächsten (schnelleren) Generation verwiesen, schon passt es wieder. Dabei kostet der neue Rechner nur einen Bruchteil dessen, was eine "Optimierung" der Software kosten würde. Thema abgehakt.

    Dazu kommt, daß sich kaum noch jemand Gedanken über eine fehlende Programm-Funktion machen muss, irgendwo gibts immer eine passende Bibliothek. Runterladen, Funktion dazulinken, fertig. Hauptsache läuft.
    Btw, ich würde echt gerne sehen, was der Intel-Compiler aus dem Code macht *sabber*


    @Marsi
    ja, als schlechter ASM-Bastler kann man keine 20 Jahre lang immer wieder und wieder von sehr guten Programmierern optimierten C-Routinen schlagen, das ist sonnenklar.
    Aber wie schon am Beispiel gezeigt, und von AspirinJunkie angesprochen, der schnellere Algorithmus macht das Rennen^^. Und ab und zu könnte man ja auch mal die "neuen", seit 10 Jahren in der Hardware verbauten Features z.B. auch mal SSE o.ä., einsetzen.


    Jetzt was in eigener Sache, hab heute in ca. 1,5h (incl. Kaffeetrinken :D ) aus der Eukalyptus-Glättfunktion eine Assembler-DLL gebastelt.
    Hab den Autoit-Code

    Spoiler anzeigen
    [autoit]

    Func _Smooth(ByRef $aP, $iS = 1)
    Local $iI = $aP[0][0]
    For $s = 1 To $iS
    $aP[1][0] = _B($aP[$iI][0], $aP[1][0], $aP[2][0], $aP[3][0])
    $aP[1][1] = _B($aP[$iI][1], $aP[1][1], $aP[2][1], $aP[3][1])
    For $i = 2 To $iI - 2
    $aP[$i][0] = _B($aP[$i - 1][0], $aP[$i][0], $aP[$i + 1][0], $aP[$i + 2][0])
    $aP[$i][1] = _B($aP[$i - 1][1], $aP[$i][1], $aP[$i + 1][1], $aP[$i + 2][1])
    Next
    $aP[$iI - 1][0] = _B($aP[$iI - 2][0], $aP[$iI - 1][0], $aP[$iI][0], $aP[1][0])
    $aP[$iI - 1][1] = _B($aP[$iI - 2][1], $aP[$iI - 1][1], $aP[$iI][1], $aP[1][1])
    $aP[$iI][0] = _B($aP[$iI - 1][0], $aP[$iI][0], $aP[1][0], $aP[2][0])
    $aP[$iI][1] = _B($aP[$iI - 1][1], $aP[$iI][1], $aP[1][1], $aP[2][1])
    Next
    EndFunc ;==>_Smooth

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

    Func _B($1, $2, $3, $4, $t = 0.5)
    Local $V1, $V2, $V3, $V4
    $V1 = (-$1 + 3 * $2 - 3 * $3 + $4) / 6.0
    $V2 = (3 * $1 - 6 * $2 + 3 * $3) / 6.0
    $V3 = (-3 * $1 + 3 * $3) / 6.0
    $V4 = ($1 + 4 * $2 + $3) / 6.0
    Return ($V3 + $t * ($V2 + $t * $V1)) * $t + $V4
    EndFunc ;==>_B

    [/autoit]

    genommen und einfach 1:1 in Asm übertragen. Wollte mal sehen, was SSE rausholen kann. Meine Vermutung hat sich bestätigt. 10-15x schneller als die "Compiler"-Ergebnisse, dank paralleler Berechnung von 4 Koordinatenpunkten gleichzeitig. Um mir nicht die Finger wundzutippen, habe ich die Größe der Struct um 2 Koordinaten-Punkte erweitert, das hat reichlich Code gespart. Soviel zum Thema Produktivität^^ Hat echte Vorteile, wenn man ein fauler Sack ist und sich vorher ein paar Gedanken macht :rofl:
    Geschummelt hab ich natürlich auch, die Berechnungen sind nur einfach genau (in 128 Bit passen halt nur 4x32Bit ), daher kann es dazu kommen, dass nach 10 Runden "Glätten" die Eckpunkte nicht pixelgenau mit den anderen Ergebnissen der Compiler übereinstimmen. Aber genau hier liegt der Hase im Pfeffer! Bei Faktor 10-15 (und ich hab mir nichtmal die Mühe gemacht den Code zu optimieren) schnellerer Laufzeit ist die Abweichung derart minimal, damit kann ich leben....

    Btw, die Assembler-dll ist nur 3.5K groß (*zum Intel-Compiler rüberschiel*)
    Der Inhalt kann nicht angezeigt werden, da er nicht mehr verfügbar ist.

    Hab natürlich mit AssembleIt und dem eingebauten Debugger die SSE-Register verfolgt, endlich mal ne Anwendung dafür ^^

    /EDIT/ hatte die falsche Zip hochgeladen...

    Dateien

    speedtest_asm.zip 3,9 kB – 332 Downloads
  • Geschwindigkeitsvergleich C, Basic, Pascal Unerwartetes Ergebnis?!

    • Andy
    • 9. Juli 2011 um 08:22

    Hi,

    Zitat

    Auch hab ich mit der von Andy vorgeschlagenen ASM Sin und Cos Variante experimentiert, jedoch wurde meine Freebasic-Dll dadurch etwas langsamer
    verwendet hab ich das hier:

    Zitat von eukalyptus


    Sub FBSinCos(Angle As Double, ByRef FbSin As Double, ByRef FbCos As Double)
    '©2008 by ytwinky, optimized by volta ;-))
    Asm
    fld qword Ptr [Angle] 'Angle -> st(0)
    fsincos 'compute sin AND cos
    mov edx, [FbCos] 'Addr. of fbCos -> EDX
    fstp qword Ptr [edx] 'St(0) = cos -> fbCos
    mov edx, [FbSin] 'Addr. of fbSin -> EDX
    fstp qword Ptr [edx] 'St(0) = sin -> fbSin
    End Asm
    End Sub

    Alles anzeigen


    Das ist deswegen langsamer, weil Freebasic diesen "Trick" schon benutzt! Während C (und auch C++) die Sinf()-Funktion aus der Bibliothek callen (keine Ahnung was die da ausrechnen, hab nach ner Viertelstunde durch den Speicher springen aufgegeben...) , setzt Freebasic den FSIN direkt ein!

    Ich habe mir die 3 Dll´s mal angeschaut, Freebasic bastelt ja wirklich einen feinen Code! Was mich echt erstaunt hatte, Pascal war der einzige Compiler, der Pi statt über eine Variable mit dem Prozessorbefehl FLDPI direkt geladen hatte, SOWAS nenn ich mal ne Optimierung^^
    Pascal erstellt fast den gleichen Code wie Basic, allerdings werden dort nach jedem FSIN/FCOS usw. nochmal die Exceptions abgefragt, in langen Loops ist das natürlich für die Laufzeit tödlich

    Was keiner der Compiler macht, ist die eigendliche Geschwindigkeitssteigerung!
    Alle Zugriffe auf die Variablen erfolgen über den Speicher, kein einziger Compiler lädt (ausser Basic wenigstens teilweise) die Variablen in die Prozessorregister und arbeitet damit!
    Selbst wenn die Variablen im Cache stehen, ist z.B. ein
    cmp ebx, [ebp+var_18]
    wesentlich langsamer als ein
    cmp ebx, eax ;vor dem loop ein MOV eax,[ebp+var_18] vorrausgesetzt^^


    Übrigens wird beim Kantenglätten-Beispiel vom "schnellen" DevC nur der "langsame" FPU-Code verwendet, Freebasic benutzt zwar SSE-Befehle, aber (uuuurgsss) NICHT skalar, d.h. es wird nur eine statt 4 Zahlen gleichzeitig berechnet!
    Wie man z.B. beim "Tunnelflug" im ASM_Tut nachschauen kann, beschleunigt sich der FPU-Code bei Verwendung von skalarem Einsatz von SSE um ca Faktor 3-4!
    Da das "Speicherrumgehopse" bei handgeschriebenem ASM-Code auch entfällt, schätze ich eine mögliche Beschleunigung mal locker auf Faktor 6 bis 8, wenn nicht sogar 10 gegenüber dem DevC-Code. Und das ist jedenfalls eine Hausnummer!

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™