Seite 2 von 2

Verfasst: 01.06.2007 11:14
von Little John
Hallo Kaeru, da hatten sich unsere Posts überschnitten ...
Kaeru Gaman hat geschrieben:

Code: Alles auswählen

F = (1=0)      ; Hier _kann_ der zuzuweisende Ausdruck in Klammern stehen. 
dieses hier ist komplett falsch!
PB unterstützt Boole'sche Ausdrücke in rechnungen und zuweisungen nicht,
bzw. nicht unbedingt mit den gewünschten ergebnissen.

Code: Alles auswählen

a = 4
b = 6
t = ( a = b )
If t = #False
  Debug "ungleich"
Else
  Debug "gleich"
EndIf
Debug "t = "+Str(t)
Du hast recht. Ich hatte das nicht näher geprüft.
Alle anderen mir bekannten prozeduralen Programmiersprachen verhalten sich so wie ich es auch für PB angenommen hatte. Dass PB sich hier anders verhält kann ich nur als skurril bezeichnen. Aber man sollte es wissen, danke für den Hinweis.

Gruß, Little John

Verfasst: 01.06.2007 11:38
von Kaeru Gaman
an dem punkt war jeder hier mal, der genug erfahrung mit anderen programmiersprachen mitgebracht hat.

es gibt ein inoffizielles workaround:
wenn man den Boole'sche Ausdruck mit einem logischen Operator verknüpft,
dann ist das ergebnis wieder #True oder #False, und kann in berechnungen einfließen.

Code: Alles auswählen

For a = 0 To 9
  b = 9 - a
  c = a * ((a > b) Or #False) + b * ((a < b) Or #False)
  Debug Str(a)+", "+Str(b)+" => "+Str(c)
Next
funktionalität für zukünftige versionen ist nicht garantiert.
ich weiß nicht einmal, ob es mit der brandneuen 4.1 noch wie erwartet funktioniert.

Verfasst: 01.06.2007 12:06
von Little John
Kaeru Gaman hat geschrieben:an dem punkt war jeder hier mal, der genug erfahrung mit anderen programmiersprachen mitgebracht hat.
Das ist beruhigend. :)
Kaeru Gaman hat geschrieben:es gibt ein inoffizielles workaround:
wenn man den Boole'sche Ausdruck mit einem logischen Operator verknüpft, dann ist das ergebnis wieder #True oder #False,
Auf Dein vorheriges Beispiel angewendet sieht das z.B. so aus:

Code: Alles auswählen

a = 4
b = 6

t = (a = b)
Debug t                   ; zeigt leider 6
t = (Not (Not (a = b)))
Debug t                   ; zeigt wie erwartet 0 (= Wert für #False)
Wenn ich im passenden Moment daran denke, kann ich damit leben.
Kaeru Gaman hat geschrieben:und kann in berechnungen einfließen.

Code: Alles auswählen

For a = 0 To 9
  b = 9 - a
  c = a * ((a > b) Or #False) + b * ((a < b) Or #False)
  Debug Str(a)+", "+Str(b)+" => "+Str(c)
Next
Berechnungen möchte ich mit Booleschen Werten ganz bestimmt nicht anstellen (siehe diese Nachricht). Aber Zuweisungen wie oben werde ich sicher dann und wann brauchen. Danke.

Gruß, Little John

Verfasst: 01.06.2007 12:49
von Kaeru Gaman
> Auf Dein vorheriges Beispiel angewendet sieht das z.B. so aus
oder so:

Code: Alles auswählen

a = 4
b = 6
t = ( (a = b) Or #False )
Debug t
mindestens ein "Bool-Cast" auf den Ausdruck muss halt vorkommen.


> Berechnungen möchte ich mit Booleschen Werten ganz bestimmt nicht anstellen

Geschmackssache. wenn Boole'sche Ausdrücke zuverlässig funktionieren,
und die zurückgegebenen werte für #True und #False eindeutig sind,
kann man damit sehr praktische dinge machen, z.b.

Code: Alles auswählen

x = x + Step * ( x < 799 ) - x * (x >= 799 )
dieses beispiel funktioniert in PB halt nur, wenn man bei beiden ausdrücken den Boolcast hinzufügt.

Verfasst: 01.06.2007 12:52
von Kurzer
Wow, danke für Eure Grundsatzdiskussion. Selbst bei solchen Kleinigkeiten kann man ja noch ne Menge falsch machen.

Ich denke, mit

Code: Alles auswählen

x = (Not x) 
...liege ich erstmal am kompatibelsten richtig, wenn x = boolsch ist.

Dat Forum ist :allright:

Verfasst: 01.06.2007 13:35
von Little John
Kaeru Gaman hat geschrieben:> Auf Dein vorheriges Beispiel angewendet sieht das z.B. so aus
oder so:

Code: Alles auswählen

a = 4
b = 6
t = ( (a = b) Or #False )
Debug t
mindestens ein "Bool-Cast" auf den Ausdruck muss halt vorkommen.
Danke, das werd' ich mir 'mal als Standard-Lösung merken. Ist eleganter als mein Not (Not ...).
Kaeru Gaman hat geschrieben:> Berechnungen möchte ich mit Booleschen Werten ganz bestimmt nicht anstellen

Geschmackssache. wenn Boole'sche Ausdrücke zuverlässig funktionieren,
und die zurückgegebenen werte für #True und #False eindeutig sind,
kann man damit sehr praktische dinge machen, z.b.

Code: Alles auswählen

x = x + Step * ( x < 799 ) - x * (x >= 799 )
dieses beispiel funktioniert in PB halt nur, wenn man bei beiden ausdrücken den Boolcast hinzufügt.
Bei ca. 99% der Leute, die sich mit Mathematik auskennen, rollen sich bei sowas die Fußnägel hoch. :D

Außerdem ist das auch noch gefährlich, denn welche (Zahlen-)Werte eine Programmiersprache verwendet um #False und #True zu repräsentieren ist willkürlich. Selbst verschiedene Basic-Dialecte verwenden unterschiedliche Werte, so benutzt z.B. PowerBasic für #True nicht 1, sondern -1. (Dass PowerBasic ebenso wie PureBasic gerne mit PB abgekürzt wird, verkleinert nicht gerade das Fehlerpotential.) Ein Code wie

Code: Alles auswählen

x = x + Step * ( x < 799 ) - x * (x >= 799 )
würde also in PowerBasic anders funktionieren als in PureBasic.
Zusätzlich zu den Nachteilen die ich bereits beschrieben habe handelt man sich hier ohne jede Not völlig unnötigerweise eine zusätzliche potentielle Fehlerquelle ein.

Gruß, Little John

Verfasst: 01.06.2007 14:22
von Kaeru Gaman
> so benutzt z.B. PowerBasic für #True nicht 1, sondern -1.
war aufm C64 genauso, wo ich mit ausdrücken rechnen gelernt hab.
ich hatte auch schon drum diskutiert, dass es in PureB genauso gemacht wird.
(weil -1 = alle bits gesetzt, 0 = alle bits gelöscht, ~0 = -1, etc.)


> ohne jede Not
und eben das ist der punkt.
PureBasic gehört nicht zu den sprachen, wo es einen Vorteil bringen würde,
es ist also höchstens "irgendwie chique", aber ohne jeden Nutzen.

wie man hier sehen kann, ist die klassische If-Variante nicht nur viel besser lesbar,
sondern auch noch annähernd doppelt so schnell:
(remember: Debugger ausschalten!)

Code: Alles auswählen

x = 0
stp = 7
timer1 = ElapsedMilliseconds()
  For n=0 To 999999999
    x = x + stp * (( x < 799 ) Or #False ) - 800 * ((x >= 799 ) Or #False )
  Next
timer1 = ElapsedMilliseconds() - timer1

x = 0
timer2 = ElapsedMilliseconds()
  For n=0 To 999999999
    x + stp
    If x > 799
      x - 800
    EndIf
  Next
timer2 = ElapsedMilliseconds() - timer2

out$ = "Boolesh Algorithm: "+Str(timer1) + #CRLF$
out$ + "Algorithm using If: "+Str(timer2)

MessageRequester("Test",Out$)
mal ganz abgesehen davon, dass die ergebnisse nicht genau übereinstimmen.
es ist also einfach widersinnig, in PB so ein Konstrukt zu benutzen.


die einzige anwendung bleibt also die zuweisung ein eine variable,
die für eine spätere auswertung den Bool-Wert rückspeichern soll.