Mehrfachbedingung vernünftig gestalten

  • Hallo zusammen!

    Ich habe folgende Bedingung:

    Code
    If $sExcelFile == "" And $sLevel0String == "" And $sLevel1String == "" And $sLevel2String == "" Then ...

    Laut der AutoIt-Hilfe werden die restlichen Bedingungen nicht mehr beachtet, wenn die erste Bedingung erfüllt ist.

    Wie bekomm ich das jetzt hin, dass ALLE Bedingungen berücksichtig werden? Muss ich da () Klammern setzen, oder muss ich das mit If's verzweigen, was allerdings ehr umständlich und unübersichtlich wäre!? Zumal ich später noch mehr Bedingungen dieser Art habe.

    VG

  • Das ganze nennt sich short-curcuit evaluation und ist eine wichtige Form um die Performance zu beschleunigung.
    Der Ansatz ist simpel: Wenn schon die erste Seite eines Or-Operators wahr ist, dann braucht man nicht mehr die rechte Seite ausführen. Im Endeffekt wird der Gesamtausdruck nämlich immer wahr.

    Genauso bei "And": Wenn schon die linke Seite falsch ist, kann die Gesamtbedingung nicht mehr wahr werden - also braucht man die rechte Seite auch nicht mehr zu prüfen.

    Da wird auch schnell klar, dass deine Aussage:

    Laut der AutoIt-Hilfe werden die restlichen Bedingungen nicht mehr beachtet, wenn die erste Bedingung erfüllt ist.

    so nicht stimmt. Bei And werden die restlichen Bedingungen nicht mehr beachtet, wenn die erste Bedingung nicht erfüllt ist.

    Will man dies umgehen kann man halt kein And oder Or verwenden.

    Ein Hack wäre BitAnd oder BitOr zu verwenden. Die machen streng genommen etwas anderes, da aber alle diese Bedingungen nur 0 oder 1 zurückgeben kommt man damit dennoch zum selben Ergebnis:

    AutoIt
    If BitAND($sExcelFile == "", $sLevel1String == "", $sLevel2String == "") Then
  • Oh ok, dann muss ich mal meine Bedingungen überdenken, vlt. hab ich auch nen Logikfehler drin!

  • Wie bekomme ich das jetzt hin, dass ALLE Bedingungen berücksichtig werden?

    Möglicherweise verstehe ich Dich ja falsch, aber bei z.B. :

    AutoIt
    Local $sA = ""
    Local $sB = ""
    Local $sC = ""
    Local $sD = "D"
    
    If $sA == "" And $sB == "" And $sC == "" And $sD == "" Then
        ConsoleWrite("OK" & @CRLF)
    Else
        ConsoleWrite("NOT OK" & @CRLF)
    EndIf

    wird auch die letzte Bedingung berücksichtigt -> $sD ist <> "" ==> NOT OK.

    EDIT : Vieeel zu langsam ;) .

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Zumal ich später noch mehr Bedingungen dieser Art habe.

    Aus eigener Erfahrung würde ich dir raten, zunächst sämtliche dieser Abfragen in verschachtelten IF-Konstrukten unterzubringen.

    Das ist für das Debugging essenziell! Ich persönlich liebe Flags (entweder 1 oder 0). Deren Kombinationen kann man, wie bereits von AspirinJunkie beschrieben, schön kurz per BitAND bzw BitOr abfragen.

    Btw. wer mit einer Compilersprache arbeitet und zeitkritische Schleifendurchläufe bearbeitet, sollte diese Abfragen so sortieren, dass der wahrscheinlichste Fall zuerst abgefragt wird.

    Branch prediction https://de.wikipedia.org/wiki/Sprungvorhersage

    Speculative execution https://de.wikipedia.org/wiki/Speculative_execution

    In AutoIt würde ich in zeitkritischen Schleifen IMMER die wahrscheinlichste Bedingung zuerst abfragen.

  • Code
    if Not ($sA & $sB & $sC & $sD) Then

    ginge auch. Lief bei mir am schnellsten

    Code
    If x = "" took: 168.9001 ms
    If x == "" took: 142.9745 ms
    If BitAnd() took: 192.7787 ms
    If (x & y) = "" took: 88.5645 ms
    If (x & y) == "" took: 82.4627 ms
    If Not (x & y) took: 80.4725 ms

    Und mit der Autoit Beta

    Code
    If x = "" took: 188.4344 ms
    If x == "" took: 166.4387 ms
    If BitAnd() took: 182.9312 ms
    If (x & y) = "" took: 86.6626 ms
    If (x & y) == "" took: 80.3188 ms
    If Not (x & y) took: 77.9772 ms
  • Code
    if Not ($sA & $sB & $sC & $sD) Then

    ginge auch. Lief bei mir am schnellsten

    Der "&" Operator interpretiert beide Seiten automatisch als String und fügt diese zusammen. "True" ist aber nicht gleich True, und "1" ist nicht gleich 1 und "0" ist nicht gleich "".

    Was du da machst sind im Prinzip 2 Sachen:
    1. Füge a, b, c, d als String zusammen. "" & "" & "" & "" = ""
    2. If Not ("") Then -> Das checkt in dem Fall ob irgendeiner der Strings nicht leer ist.

    Wo das funktioniert: Wenn du ganz genau weißt welche Typen verwendet werden, und du tatsächlich "leere Strings" als "False" oder als "0" verwenden willst.
    Wo das nicht funktioniert: Überall sonst. Angenommen $sA = 0, dann ist der Ausdruck: If Not ("0") Then. "0" ist aber kein "leerer String" und wird daher nicht als "False" interpretiert.

    M

  • Ich denke schon, dass er wusste, was die "&"-Methode bei ihm genau macht.
    Man sollte aber schon dazuschreiben, dass dies ein Hack für diesen absoluten Spezialfall hier - prüfe mehrere Variablen auf Leerstring - ist und keine allgemeine Lösung um eine verkettete logische And-Verknüpfung zu ersetzen.

    Nicht das JBO oder andere dass einfach damit ersetzen und das 100x gut geht (da eben der Spezialfall greift) und beim 101. mal alles auf einmal Probleme macht.

    if Not ($sA & $sB & $sC & $sD) Then

    ginge auch. Lief bei mir am schnellsten

    Da wir gerade bei Spezialfällen sind: Im konkreten Beispiel zieht keine short-curcuit-evaluation, da ja alle Teilbedingungen wahr sind.
    Kannst ja mal $sA = "1" setzen und nochmal testen.

    Und anschließend nochmal alle Variablen mit längeren Strings vorbelegen.

    Dann sollte das verkettete And die schnellste Variante sein.

    Es hängt also enorm vom konkreten Anwendungsfall ab (worüber wir keine Info haben) bevor man wirklich richtig optimieren kann.

  • Es hängt also enorm vom konkreten Anwendungsfall ab

    Eben! Und damit plädiere ich wieder mal für die verschachtelte IF-Konstruktion. DIE ist nämlich in jedem Schritt debuggbar, was man von if Not ($sA & $sB & $sC & $sD) Then mal nicht behaupten kann.

    Ich postuliere auch mal, dass geschätzt 50% aller Forenfragen, die sich auf die Logik im Code beziehen, die "funktioniert nicht"-Anfrage aufgrund fehlendem Debugging bzw. Ahnungslosigkeit des Users was sich in seinen Variablen befindet, beziehen. Unabhängig von der Programmiersprache....

    AutoIt´s Segen bezüglich der Datentypen ist gleichzeitig sein Fluch.

    Wo das funktioniert: Wenn du ganz genau weißt welche Typen verwendet werden, und du tatsächlich "leere Strings" als "False" oder als "0" verwenden willst.
    Wo das nicht funktioniert: Überall sonst. Angenommen $sA = 0, dann ist der Ausdruck: If Not ("0") Then. "0" ist aber kein "leerer String" und wird daher nicht als "False" interpretiert.

    wzbw... :thumbup: Wenn man genau weiß was man tut, ist es auch total einfach ^^

  • Genau die Variante die ich da gepostet habe macht nur sinn wenn man prüfen will ob alle der String Variablen Leer sind. Ansonsten, wie schon ausgeführt wurde, wird autoit sowas wie ein Bool False in String "False" umwandeln was buggs hervorrufen könnte.

  • wird autoit sowas wie ein Bool False in String "False" umwandeln was buggs hervorrufen könnte.

    "Bugs" sind das nicht! Jedenfalls nicht, solange der "Programmierer" weiß, was er da tut. Ein Bug ist ein Fehler in einem Programm wo der Programmierer eben genau an dieser Stelle NICHT gewußt hat, was er da tut oder "davon ausgegangen ist" das das richtig war was er getan hat.

    Wenn der Inhalt der Variablen und deren Typ klar sind, und auch nachvollzogen werden können, dann ist es schwer, "Bugs" zu erzeugen.

    Daher gibt es in AutoIt/Scite in den Tools ja auch die Menge an Debugging-Funktionen, die imho viel zu wenig genutzt werden...