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

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

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

Beitrag 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?
Zuletzt geändert von Regenduft am 01.04.2008 21:29, insgesamt 1-mal geändert.
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Zuletzt geändert von Kaeru Gaman am 01.04.2008 18:01, insgesamt 1-mal geändert.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

1. OR nimmt nur einen Bit (oder irgendwie anders kA) und | alle
2. teste es doch
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Beitrag 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...
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag 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
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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....
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Beitrag 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:
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Beitrag 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...
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten