Logische Operationen

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Logische Operationen

      In diesem Artikel, der in erster Linie GML-Anfängern gewidmet ist, will ich den Umgang mit binären Zahlen erläutern. Diese richtig zu verwenden kann sehr nützlich sein und einiges an z.B. benötigtem Arbeitspeicher oder auch an Programmieraufwand einsparen.

      Erst einmal ist eine binäre Zahl nur eine Zahl anders dargestellt, nämlich als eine Reihe von "Bits", wobei jedes Bit nichts anderes ist als eine Bool'sche Variable (true oder false).
      Sehen wir uns mal folgendes Beispiel an: Eine Spielwelt besteht aus Spielfeldern verschiedenen Typs: Grasland, Wald, Berge oder Wasser. Man hat also für jedes Spielfeld eine Zahl, die den Typ angibt - z.B. so

      Quellcode

      1. Gras=1; Wald=2; Berge=3; Wasser=4
      2. SpielfeldTyp = Gras

      Diese Zuordnung geht spätestens dann in die Hose, wenn ein Spielfeld Wald und Berge haben soll. Deshalb benutze ich an dieser Stelle folgende Zahlenwerte:

      Quellcode

      1. Gras=1; // 2 hoch 0
      2. Wald=2; // 2 hoch 1
      3. Berge=4; // 2 hoch 2
      4. Wasser=8; // 2 hoch 3

      Diese Zahlen (auch Zweierpotenzen genannt) haben den großen Vorteil, daß sie den einzelnen Bits einer Binärzahl entsprechen. Ich kann also jedes Bit einzeln "setzten" oder "löschen", indem ich schreibe:

      Quellcode

      1. SpielfeldTyp = Wald + Berge

      Man kann natürlich binäre Zahlen mit Dezimalzahlern mischen, also z.B. die untersten vier Bits (dezimal 0-15) stehen für Terrain-Höhe und Bits 4-7 für den Terrain-Typ.


      Bitweise Operationen

      Diese normale Addition

      Quellcode

      1. SpielfeldTyp += Wald

      funktioniert natürlich nur, wenn der Wert für Wald nicht schon in der Zahl enthalten ist. Ebenso würde

      Quellcode

      1. SpielfeldTyp -= Wald
      zu falschen Ergebnissen führen, wenn der Wert NICHT enthalten wäre. Also wird eine andere Methode benutzt, um einzelen Bits zu setzten, zu löschen und vor allem zu LESEN - denn wir wollen ja genau wissen, welche Bits gesetzt sind und welche nicht.

      Um also einelne Bits zu setzen, schreibt man normalerweise (z.B. für Bit2):

      Quellcode

      1. SpielfeldTyp = SpielfeldTyp | Bit2 // logisch "oder"

      Anmerkung: Ich würde an dieser Stelle tatsächlich "4" schreiben für Bit2 und nicht "power(2,2)" oder so. Ist einfach schneller.

      Will ich das Bit2 löschen, benutze ich xor:

      Quellcode

      1. SpielfeldTyp = SpielfeldTyp ^ Bit2 // logisch "exklusiv-oder"

      Zum Auslesen der einzelnen Bits nimmt man schließlich

      Quellcode

      1. Wald = SpielfeldTyp & Bit2 // logisch "und"


      Jetzt kommt aber das interessanteste: Der Computer liebt es, mit einzelnen Bits zu rechnen. Soll heißen, bitweise Operationen (and, or, xor) gehen extrem schnell, weil das die reine Maschinensprache ist. (Kann sein, daß ich mich beim Game Maker jetzt irre, denn ich weiß nicht genau wie der GML-code nach dem Kompilieren aussieht)
      Wer diese Operationen nicht kennt und deren vielfältige Anwendungsmöglichkeiten zu schätzen weiß, dem schlage ich vor, einfach mal bei Wikkipedia nachzulesen oder nach Bool'schen Operationen zu googeln.
      Man kann zum Beispiel alle Bits einer Speicherstelle umkehren, verschieben oder einzelne Bits "rausfiltern" - ich kann sagen: gib mir nur die Bits 0-3 aus, der Rest interessiert mich jetzt gerade nicht. Oder, was ich oft benutze, ist Schalter "umschalten" mit

      Quellcode

      1. a=a^1
      anstelle von

      Quellcode

      1. if (a=0) a=1 else a=0

      Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von Melancor ()

    • Der Game Maker (zumindest Version6) benutzt bis zu 64 Bits für numerische Variablen. Ich finde das gerade voll spannend, weil ich so immer mehr Daten in immer weniger Variablen unterbringen kann, bzw. viel weniger Speicher brauche. Ein Beispiel:
      Mein Imperium verfügt über viele, viele Kolonien. Ich brauche dringend eine ds_list, wo alle Kolonien drinstehen. Es kommen immer neue dazu, und ich verliere öfter mal welche an den Feind. Ohne ds_list ist das einfach ätzend. Aber in eine Liste paßt je nur ein Wert, deshalb brauche ich eine REIHE von Listen: Eine für Population, eine für Geld, und eine für - oje... es gibt 30 verschiedene Gebäude, die wir irgendwie gespeichert haben wollen.
      Ich kann also alle 30 Gebäude locker in eine einzige Zahl packen. Ich habe sogar zwei Bits pro Gebäude zur Verfügung, und könnte auch noch definieren in welchem Zustand (0,1,2,3) jedes Haus ist.
      Der Geiz mit dem Arbeitsspeicher steht eher nicht im Vordergrund. Bei komplexeren Spielen versuche ich aber zunehmend, die Daten möglichst KOMPAKT zu halten. Man könnte natürlich ebensogut einen String für sowas verwenden.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Melancor ()

    • Benutzer online 1

      1 Besucher