Ein paar Worte vorabHome   Letzte MeldungenNews   Index der Kapitel und der besprochenen FunktionenIndex   Wer ich bin, warum ich diese Seiten mache, KontaktImpressum   Ich freue mich über jeden Eintrag im Gästebuch!Gästebuch   Einige Links zu anderen AutoLisp-SeitenLinks   Copyrights und DisclaimerRechts
Hier können die kompletten Seiten als ZIP-File heruntergeladen werden!

Berechnen von arithmetischen Ausdrücken in der Kommandozeile Sitz!Platz!Fass!
Das Verschachteln von Ausdrücken Alte Schachtel!
Das Speichern von Werten in Variablen Gebunkert
Verhindern der Evaluation mit Quote Bergbäche
Erzeugen von einfachen Listen in AutoLisp Brot,Eier,Käse
Einfache Funktionen zur Listenbearbeitung ...um die Wurst
Funktionen für den Zugriff auf Listenelemente Was ein Salat!
Über Haupt- und Nebeneffekte von Funktionen Schwer schuften
Das Definieren von eigenen Funktionen in AutoLisp Ostfriesischer...
Lokale Variablen und Funktionsargumente in AutoLisp Kondome!
Das Laden von Programmdateien in AutoLisp Banküberfall
Verzweigung in Funktionen aufgrund von Entscheidungen Wenn das Wort...
Zusammenfassen von Entscheidungen mit den Logik-Funktionen Ins Schweinderl
Mehrfach-Verzweigungen in AutoLisp mit Cond 3. Strasse links
Schleifen zum Steuern des Ablaufs in AutoLisp-Funktionen Wie im Fernsehen
Testfunktionen zum Steuern von Schleifen in AutoLisp Schwanger?
Gleichheitstests als Schleifenkriterium in AutoLisp Noch gleicher?
Zeichneketten-Bearbeitung in AutoLisp Rauchzeichen
Funktionen zur Konvertierung von Datentypen in AutoLisp Wasser zu Wein
Komplexere Funktionen für die Bearbeitung von Listen in AutoLisp Nicht arbeiten...
Das Erzeugen von anonymen Funktionen mit lambda Schwarze Kutte
Das Bearbeiten von Listenelementen mit foreach Jedem das Seine
Erzeugen und Verwenden von Assoziationslisten in AutoLisp Beim Psychiater
Zugriff auf Geometriedaten und Erzeugen von Geometrieelementen Ententanz
Der Umgang mit Auswahlsätzen in AutoLisp Jung gefreit, ...
Auswahl von AutoCAD-Zeichnungsgeometrie mit ssget Raffgierig!
Verändern von Zeichnungs-Geometrie mit entmod Flickschusterei
Das Erzeugen von Geometrie mit entmake Houdini
Vom Umgang mit Bits in AutoLisp, Teil 1 Prinzessin auf...
Vom Umgang mit Bits in AutoLisp, Teil 2 Franzosen
Über Programmierstile in AutoLisp, Teil 1 Emma
Über Programmierstile in AutoLisp, Teil 2 Sti(e)lblüten
Über Programmierstile in AutoLisp, Teil 3 Eingewickelt
Über Programmierstile in AutoLisp, Teil 4 Doofe Frisur?


Zum den Seiten für Fortgeschrittene

Zu den ActiveX-Seiten

Meine Private HP mit Fotos, Gedichten, Musik und Postkartenversand

Mein Online-Lexikon der Fotografie

Mein völlig abgedrehtes Reisebüro










Nun, allzuoft haben wir es in AutoLisp mit Bits nicht zu tun. Da aber AutoCAD einige Systemvariablen und auch Elementdaten binär speichert, muss man sich als AutoLisp-Programmierer auch damit auskennen. Trotzdem, gegenüber den meisten anderen Programmiersprachen bleibt uns das Schlimmste erspart: Hexadezimale Zahlen treten eigentlich nie auf, und das bedeutet, dass wir uns auf grundlegende Techniken der binären Verarbeitung beschränken können.

Wir wissen, dass ein Rechner intern ja alles in binärer Form (d.h. ausschliesslich aus Nullen und Einsen zusammengesetzt) darstellt. Mit einem einzigen Bit können zwei Zustände kodiert werden, aber mit zwei Bits sind es schon vier: 00, 01, 10, 11. Drei Bits erweitern den Bereich schon auf 8 Zustände (000, 001, 010, .... 110, 111). Es ist nichts schwer nachzuvollziehen, dass es bei 4 Bits dann 16 werden usw.

Es ist doch einfach so, dass sich jedesmal, wenn ein weiteres Bit hinzukommt, die Anzahl der bisherigen Kombinationen verdoppelt. Um das nun ein wenig mathematischer zu formulieren: die Anzahl der Möglichkeiten ist 2 hoch Anzahl der Bits. Ein Byte (8 Bits) kann also 256 verschiedene Zustände annehmen, denn 2 hoch 8 ist 255.

Eine Bit-Codierung begegnet uns z.B. bei der Systemvariablen OSMODE - hier werden die derzeit eingestellten (aktiven) Objektfänge gespeichert. Der Objektfang END hat den Wert 1, und MIT hat den Wert 2. ZEN hat dann aber schon den Wert 4, und das ist der springende Punkt: Hätte ZEN den Wert 3, wäre das nicht eindeutig! 3 könnte ja auch bedeuten, dass END und MIT (1 und 2) gleichzeitig aktiv sind. Daher muss jeder zusätzliche Wert doppelt so gross wie der Vorgänger ausfallen.

Binär dargestellt, werden die Dinge plötzlich ganz einfach:
00000001  =  1 (END)
00000010  =  2 (MIT)
00000011  =  3 (END + MIT)
00000100  =  4 (ZEN)
00000101  =  5 (ZEN + END)
00000110  =  6 (ZEN + MIT)
00000111  =  7 (ZEN + MIT + END)
00001000  =  8 (PUN)
                  
Wir sehen, dass das erste (rechte) Bit immer für END zuständig ist, das zweite (von rechts) für MIT usw.

Etwas schwieriger wird folgende Frage: Welche Ofänge sind denn aktiv, wenn OSMODE gerade den Wert 37 hat? Wer aufmerksam mitgedacht hat, wird auf Anhieb sehen, dass END auf jeden Fall dabei sein muss, denn 37 ist eine ungerade Zahl! Aber alles Weitere ist auf Anhieb mit blossem Auge nicht so leicht zu erkennen. AutoLisp stellt uns aber einige Funktionen für den Umgang mit Bits und Bytes zur Verfügung, die jetzt hier besprochen werden sollen.

Die erste dieser Funktionen heisst (logand) - hier liegt allerdings eine Namensverwirrung vor: Es handelt sich NICHT um das logische UND (diese Funktion heisst schlicht (and ...)! Hier geht es um Bits! Wir müssen also mit dem irreführenden Namen leben. Auf jeden Fall vergleicht diese Funktionen zwei Zahlen miteinander und gibt als Ergebnis eine neue Zahl zurück. Dabei passiert Folgendes: Da, wo in beiden Input-Zahlen ein Bit gesetzt ist, wird es auch im Ergebnis gesetzt. Ein paar Beispiele:
(logand 19 49) => 17

00010011 Die erste Vergleichszahl ist 19
00110001 Die andere lautet 49
--------
00010001 Das Ergebnis ist 17

(logand 31 63) => 31

00111111 63
00011111 31
--------
00011111 31

(logand 170 85)

10101010 170
01010101  85
--------
00000000   0
                  
Es ist offensichtlich, dass die Reihenfolge der Argumente keine Rolle spielt. Wenn wir testen wollen, ob z.B. der Ofang SCH (32) aktiv ist, verwenden wir folgende Formulierung:
(= 32(logand 32 (getvar"OSMODE")))
; prüft, ob Bit 6 gesetzt ist
                  
Die Darstellung wurde bisher auf ein Byte begrenzt. Allerdings arbeiten die Bit-Funktionen in AutoLisp auch mit grösseren Zahlen, das Maximum für Ganzzahlen liegt bei AutoCAD/AutoLisp bei 32 Bit. Schwierig wird die Angelegenheit übrigens bei negativen Zahlen, da hier die Darstellungsform, d.h. die Bit-Anordnung, nicht ganz einfach zu verstehen ist. Da der bitweise Umgang mit negativen Zahlen aber in AutoLisp keine Rolle spielt, werde ich darauf auch nicht eingehen.

Die Funktion (logior) ist ähnlich, aber hier werden die Zahlen nicht verUNDet, sondern verODERt, um's mal auf Programmiererdeutsch zu sagen. Das bedeutet: Da, wo in einer der beiden Eingangszahlen (oder auch in beiden) ein Bit vorhanden ist, wird es auch in der Ausgangszahl gesetzt. Noch einmal unsere Beispielzahlen:
(logior 19 49) => 51

; Erläuterung:

00010011 Die erste Vergleichszahl ist 19
00110001 Die andere lautet 49
--------
00110011 Das Ergebnis ist 51

(logior 31 63) => 63

00111111 63
00011111 31
--------
00111111 63

(logior 170 85) => 255

10101010 170
01010101  85
--------
11111111 255
                  
Ein weiteres Beispiel, mit dem auch gleich einmal der Umgang mit grösseren Zahlen demonstriert werden kann: Die Werte für OSMODE gehen von 1 (END) bis 8192 (PARallel). Es gibt dann aber auch noch den Wert 16384, mit dem der Objektfang temporär ein- bzw. ausgeschaltet werden kann. Bei diesem Wert handelt es sich übrigens um das 15. Bit (wer's nich glaubt, sollte einmal (expt 2 14) eingeben (nicht 15, sondern 14!).

Um zu testen, ob der Objektfang derzeit deaktiviert ist, verwenden wir also das hier:
(/= 0 (logior 16384 (getvar "OSMODE")))
;oder
(/= 0 (logior (expt 2 14) (getvar "OSMODE")))
                  
Und so würde der temporär deaktivierte Ofang END + ZEN + SCH binär aussehen (die Leerstelle in der Binärdarstellung dient nur der Lesbarkeit):
01000000 00100011   16384 + 37 = 16421
                  
Um die beiden Funktionen (logand) und (logior) noch einmal zu vergleichen, möchte ich hier kurz noch erklären, was eine 'Wahrheitstafel' ist: Nichts weiter als eine kleine Tabelle, die die Verknüpfung darstellt. Im nächsten Kapitel werden wir diese Wahrheitstafeln des öfteren brauchen:
          In   Out                   In   Out
logand:   0 0 |  0         logior:   0 0 |  0
          0 1 |  0                   0 1 |  1
          1 0 |  0                   1 0 |  1
          1 1 |  1                   1 1 |  1
                  
Und nun noch eine paar Worte zum Verschieben von Bits, wozu uns AutoLisp die Funktion (lsh ...) bereitstellt. Alle Bits werden um eine oder mehr Stellen nach links verschoben. Dabei wird von rechts her mit Nullen ergänzt. Zunächst ein (optisches) Beispiel:
(lsh 57 1)  = 114

00111001      57
--------
01110010      114
                  
Falls wir z.B., was durchaus denkbar wäre, die Zahl 16384 einmal nicht im Kopf parat haben sollten, aber noch wissen, dass es hier um das 15. Bit ging, können wir auch die Zahl 1 nehmen und um 14 Bits nach links schieben:
(lsh 1 14)  =>  16384
                  
Ein weiteres Beispiel ergibts sich, wenn wir (mit ActiveX-Methoden) die AutoCAD-Hintergrundfarbe ändern möchten. Hier werden keine ACI-Farbnummern erwartet, sondern 24-bittige Windows-Farben. Jeweils 8 Bit sind einem der drei Farbkanäle Rot, Grün und Blau zugeordnet. Nehmen wir einmal an, wir haben getrennt vorliegende Farbangaben wie 50% Rot, 25% Grün, 25% Blau. Wie kann man diese Werte in eine Frabnummer umrechnen?

Zunächst einmal müssen die Prozentangaben in Werte umgerechnet werden:
(fix(+ 0.5(* 0.5 255)))  =>  128
(fix(+ 0.5(* 0.25 255))) =>  64
                  
Dann müssen wir den Rot-Wert um 16 Stellen und den Grün-Wert um 8 Stellen nach links shiften und die drei Werte addieren:
(+ (lsh 128 16) (lsh 64 8) 64) => 8405056
                  
Es gibt zwar die Funktion (lsh), was left shift bedeutet, in AutoLisp, aber kein (rsh) - für einen right shift können wir aber jederzeit (lsh) mit einem negativen zweiten Argument verwenden. Bits, die dabei rechts herausfallen, verschwinden einfach, und von links her wird immer mit Nullen aufgefüllt.

Bleiben wir bei unserem Farb-Beispiel: Um den Grünkanal einer uns unbekanneten Windows-Farbnummer auszuwerten, verwenden wir also diesen Ausdruck:
(logand 255 (lsh <farbe> -8))
                  
Falls das jetzt nicht sofort einsichtig sein sollte: Zunächst wird mit (lsh) um 8 Stellen nach rechts verschoben, der Blaukanal geht dabei über den Jordan. Um aber den Rot- vom Grünkanal abzutrennen, verwenden wir auch noch (logand 255 ...). So wird sichergestellt, dass im Ergebnis nur die rechten 8 Bits enthalten sind. Die optische Darstellung (wir nehmen wieder die Farbe 8405056):
10000000 01000000 01000000     8405056  ;Farbnummer

00000000 10000000 01000000       32832  ;lsh
00000000 00000000 11111111         255  ;logand
--------------------------
00000000 00000000 01000000          64  ;Ergebnis
                  
Diese Darstellungen sollten als Grundlage bzw. als Einstieg in die Bit-Funktionen von AutoLisp genügen. Im nächsten Kapitel werden wir uns mit (boole ...) befassen, einer sehr komplexen Funktion, die das Ganze noch erweitert. Zum Schluss aber noch eine kleine, selbstdefinierte Funktion, mit der man sich Zahlen binär ausgeben kann. Zum Üben und Nachvollziehen ist das ungemein parktisch:
(defun prinbin(zahl / i str)
  (setq i 0 str "")
  (repeat 32
    (setq str
      (strcat str
        (itoa
          (logand 1(lsh zahl(- i 31)))
        )
      )
    )
    (setq i(1+ i))
    (if(zerop(rem i 8))
      (setq str(strcat str" "))
    )
  )
  (strcat str ": " (itoa zahl))
)
                  
Wir probieren die Funktion einfach ein bisschen aus:
(prinbin 255) =>
"00000000 00000000 00000000 11111111  : 255"

(prinbin 170)
"00000000 00000000 00000000 10101010  : 170"

(prinbin (+ (lsh 255 16)(lsh 255 8)255))
"00000000 11111111 11111111 11111111  : 16777215"
; das ist übrigens die Farbe 'weiss' als
; Windows-Farbnummer! Alle 3 Farbkanäle
; haben den Maximalwert 255