Seite 1 von 2

"OR" oder "|" *gelöst*

Verfasst: 01.04.2008 17:51
von Regenduft
Wie schaut's, weiß jemand was schneller ist? Das "OR" oder das bitweise Or "|"?

Ich denke mal das macht kaum 'nen Unterschied, aber wie sieht das genau aus?

Verfasst: 01.04.2008 17:59
von Kaeru Gaman
Or ist die logische verknüpfung für Ausdrücke, | die bitweise für Zahlen.
beides solltest du besser nicht durcheinander werfen.

also

Code: Alles auswählen

If a=1 Or b=2
funktioniert, aber

Code: Alles auswählen

If a=1 | b=2
liefert dir unvorhersagbare ergebnisse.

abenso liefert

Code: Alles auswählen

$8000 | $0400
einfach $8400, wie es sein soll,
aber was bei

Code: Alles auswählen

$8000 Or $0400
rauskommt, hab ich noch nicht ausprobiert, auf die idee bin ich noch nicht gekommen.

Verfasst: 01.04.2008 17:59
von Andreas_S
1. OR nimmt nur einen Bit (oder irgendwie anders kA) und | alle
2. teste es doch

Verfasst: 01.04.2008 18:29
von Regenduft
Danke für die flotte Antwort, aber...

Das "Or" und "|" anders arbeiten und wie sie arbeiten ist mir schon klar:
"Or" arbeitet mit True (nicht Null) und False (Null).
"|" arbeitet Bitweise.

Manchmal kann man aber "gleich verwertbare" Ergebnisse erziehlen!

Hier ein Beispiel:

Code: Alles auswählen

; === TEST NR.1 =======

If %00 Or %01
  Debug "Check 1 -> OR"
Else
  Debug "WTF?"
EndIf

If %00 | %01
  Debug "Check 1 -> |"
Else
  Debug "WTF?"
EndIf

Debug ""

; === TEST NR.2 =======

If %00 Or %00
  Debug "WTF?"
Else
  Debug "Check 2 -> OR"
EndIf

If %00 | %00
  Debug "WTF?"
Else
  Debug "Check 2 -> |"
EndIf

Debug ""

; === TEST NR.3 =======

If %01 Or %10
  Debug "Check 3 -> OR"
Else
  Debug "WTF?"
EndIf

If %01 | %10
  Debug "Check 3 -> |"
Else
  Debug "WTF?"
EndIf
Mit Variablen funzt das ja natürlich auch!
Also: Was ist jetzt jeweils schneller?

@ Andreas_S: Ich habe leider keine Ahnung wie ich die Geschwindigkeit am besten teste...

Verfasst: 01.04.2008 18:41
von Kaeru Gaman
also, wenn du fälle findest, wo du optional programmieren kannst, dann teste das ruhig mal selber aus.

für einen test setzt du ein proggi auf, wo du NUR DIESE operation
zig-tausend-mal durchführst in einer einfachen schleife,
und vorher den Wert von ElapsedMilliseconds() notierst,
und nachher die differenz ausgibst.

dafür musst du aber den debugger abgeschaltet haben beim durchlauf,
sonst hat das ergebnis keine aussagekraft.

Verfasst: 01.04.2008 19:07
von NicTheQuick
Eigentlich ganz einfach.

Code: Alles auswählen

If a Or b
  c = 1
Else
  c = 2
EndIf
Wenn hier a <> 0 ist, gehts direkt weiter mit c = 1 und b wird nicht mehr beachtet.
Wenn a = 0 ist, wird geprüft, ob b <> 0 ist und wenn ja geht es weiter mit c = 1; wenn nicht, geht es weiter mit c = 2.

Code: Alles auswählen

If a | b
  c = 1
Else
  c = 2
Endif
Hier werden a und b in zwei Register gelesen, dann wird das bitweise Oder
angewendet und dann wird mittels CMP überprüft, ob das Ergebnis
ungleich Null ist. Wenn ja, geht es mit c = 1 weiter, sonst mit c = 2.


Zusammenfassung:
Wenn man weiß, dass a statistisch öfter ungleich Null ist als b, schreibt
man 'If a Or b', sonst 'If b Or a'.
Falls im Code statt a und b Funktionen stehen, die auf jeden Fall
aufgerufen werden müssen, weil sie womöglich noch global etwas ändern,
schreibt man entweder 'If Funktion1() | Funktion2()', weil dann sicher
beide aufgerufen werden, auch wenn 'Funktion1()' Null ist, oder man
schreibt das Ergebnis der zweiten Funktion in eine Hilfsvariable vor der If-Zeile ('tmp = Funktion2() : If Funktion1() Or tmp'), was natürlich nur
sinnvoll ist, wenn 'Funktion2()' auch vor 'Funktion1()' aufgerufen werden
darf. Wenn die Reihenfolge der Funktionsaufrufe wichtig ist, braucht man
natürlich zwei Hilfsvariablen.
Die Möglichkeit 'If a | b' ist also hinfällig, da langsamer.

Zum Überblick nochmal ein Code und der passende ASM-Ausschnitt:

Code: Alles auswählen

a = 1
b = 2

If a Or b
  c = 1
Else
  c = 2
EndIf

If a | b
  c = 3
Else
  c = 4
EndIf

Code: Alles auswählen

; :
; a = 1
  MOV    dword [v_a],1
; b = 2
  MOV    dword [v_b],2
; 
; If a Or b
  CMP    dword [v_a],0
  JNE   _AO_Ok0
  CMP    dword [v_b],0
  JNE   _AO_Ok0
  JMP   _AO_No0
_AO_Ok0:
  MOV    eax,1
  JMP   _AO0
_AO_No0:
  XOR    eax,eax
_AO0:
  AND    eax,eax
  JE    _EndIf2
; c = 1
  MOV    dword [v_c],1
; Else
  JMP   _EndIf1
_EndIf2:
; c = 2
  MOV    dword [v_c],2
; EndIf
_EndIf1:
; 
; If a | b
  MOV    ebx,dword [v_a]
  OR     ebx,dword [v_b]
  AND    ebx,ebx
  JE    _EndIf5
; c = 3
  MOV    dword [v_c],3
; Else
  JMP   _EndIf4
_EndIf5:
; c = 4
  MOV    dword [v_c],4
; EndIf
_EndIf4:
Und zur Verdeutlichung nochmal das mit den Funktionsaufrufen:

Code: Alles auswählen

Global a.l, b.l

Procedure a()
  Debug "a"
  ProcedureReturn a
EndProcedure

Procedure b()
  Debug "b"
  ProcedureReturn b
EndProcedure

Debug "Mit 'Or' und a=1 und b=2:"
a = 1
b = 2
If a() Or b()
  c = 1
Else
  c = 2
EndIf

Debug "Mit 'Or' und a=0 und b=2:"
a = 0
b = 2
If a() Or b()
  c = 1
Else
  c = 2
EndIf

Debug "Mit '|' und a=0 und b=2:"
If a() | b()
  c = 3
Else
  c = 4
EndIf

Verfasst: 01.04.2008 19:43
von Kaeru Gaman
wie gesagt, je nachdem was ich "or" vergleichen will.

übersetz mir mal

Code: Alles auswählen

If XPos < CheckPos Or XPos > Checkpos + TileWidth
mit nem "|", so dass es auch immer funktioniert.... ;)

aber danke @nic für die aufklärende ausführung. :allright:

PS:
der Ersteller hat ein Post gelöscht, auf das ich ursprünglich geantwortet hatte, nur fürs protokoll....

Verfasst: 01.04.2008 20:00
von Regenduft
@ NicTheQuick: Danke! Mir haben sich gerade Horizonte geöffnet!

@ Kaeru German: Sorry fürs gelöschte Post... A) hatte ich erst 'nen Denkfehler in meinem Leistungstest und B) war beim Posterstellen noch nicht die Antwort von NicTheQuick vorhanden.

Irgendwas mache ich falsch meine Posts enden irgendwie immer mit einem oops :oops:

Verfasst: 01.04.2008 20:08
von Regenduft
Noch zum Spaß @ Kaeru German

Code: Alles auswählen

If XPos < CheckPos Or XPos > Checkpos + TileWidth
enstspricht (glaube ich):

Code: Alles auswählen

If (XPos < CheckPos) | (XPos > Checkpos + TileWidth)
...aber jetzt mache ich mich lächerlich :lol: nicht dass der ganze Thread noch im Müll landet...

Verfasst: 01.04.2008 20:19
von Kaeru Gaman
du bist neu in PB, gell?

ein (Value Compare Value) ergibt nicht zwangsweise #True oder #False,
wie in anderen Hochsprachen, sondern liefert vielmehr den überlegenen Registerwert zurück.

PB kennt keine nativen Boole'sche Ausdrücke!

es gibt ein workaround in PB, nämlich ((Value Compare Value) And/Or Bool),
damit du wirklich eine Zahlenmäßig brauchbare boole'sche Auswertung deines Ausdrucks bekommst.