Mit bitweisen Operationen können wir einzelne Stellen innerhalb von Binärzahlen gezielt verändern.
Elm stellt in seinem Bitwise-Modul mehrere bitweise Operatoren bereit.
Das Verändern einzelner Bits einer Zahl nennt man Maskierung.
Eine Maske ist eine Zahl, bei der bestimmte Bits auf eine bestimmte Weise gesetzt sind, um mit bitweisen Operatoren wie and, or und xor eine andere Zahl zu bearbeiten.
and kombiniert zwei Zahlen, indem nur die Bits beibehalten werden, die in beiden Zahlen 1 sind.
Das ist nützlich, um zu prüfen, ob ein einzelnes Bit gesetzt ist.
Um zum Beispiel zu prüfen, ob das 4. Bit einer Zahl auf 1 gesetzt ist, verknüpfst du sie mit and und einer Maske 01000 (8 im Dezimalsystem) und schaust, ob das Ergebnis ungleich null ist:
Bitwise.and 13 8 --> 8
-- 13 = 01101
-- 8 = 01000
-- and = 01000 = 8
or kombiniert zwei Zahlen, indem jedes Bit auf 1 gesetzt wird, wenn es in einer der beiden oder in beiden Zahlen 1 ist.
Das ist nützlich, um ein bestimmtes Bit auf 1 zu setzen.
Um zum Beispiel das 2. Bit in 10101 zu setzen, verknüpfst du es mit or und der Maske 00010:
Bitwise.or 21 2 --> 23
-- 21 = 10101
-- 2 = 00010
-- or = 10111 = 23
xor kombiniert zwei Zahlen, indem jedes Bit auf 1 gesetzt wird, wenn es in einer Zahl 1 und in der anderen 0 ist.
Das ist nützlich, um ein Bit in seinen entgegengesetzten Wert umzudrehen:
Bitwise.xor 20 5 --> 17
-- 20 = 10100
-- 5 = 00101
-- xor = 10001 = 17
complement invertiert jedes Bit einer Zahl (0 wird zu 1, 1 wird zu 0).
Beachte, dass dadurch positive Zahlen negativ und negative Zahlen positiv werden.
Das liegt daran, dass negative Zahlen im Binärsystem mit einer 1 an der linken Position dargestellt werden.
Bitwise.complement 21 --> -22
-- 21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
Die folgenden Operatoren verschieben Bits um eine bestimmte Anzahl von Positionen nach links oder rechts und multiplizieren oder dividieren damit effektiv mit Zweierpotenzen.
shiftLeftBy verschiebt Bits nach links und füllt von rechts mit 0 auf.
Um zum Beispiel 21 um 3 Stellen nach links zu verschieben:
Bitwise.shiftLeftBy 3 21 --> 168
-- 21 = 10101
-- shiftLeftBy 3 = 10101000 = 168
Das ist dasselbe wie 21 * 2^3 = 21 * 2 * 2 * 2 = 168.
shiftRightBy: Verschiebt Bits nach rechts:
Bitwise.shiftRightBy 2 21 --> 5
-- 21 = 10101
-- shiftRightBy 2 = 00101 = 5
Um 2 Stellen nach rechts zu verschieben, ist dasselbe wie eine Ganzzahldivision durch 4.
Beachte, dass diese Funktion den Wert des linken Bits dupliziert. Negative Zahlen bleiben also negativ:
Bitwise.shiftRightBy 3 -21 --> -3
-- -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3
Wenn du nach rechts verschieben und mit Nullen auffüllen möchtest, verwendest du shiftRightZfBy:
Bitwise.shiftRightZfBy 3 -21 --> 536870909
-- -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909
Dein Freund hat dir gerade eine Nachricht mit einem wichtigen Geheimnis geschickt. Damit es andere nicht leicht haben, sie zu lesen, wurde die Nachricht durch eine Reihe von Bitmanipulationen verschlüsselt. Du musst nun die Funktionen schreiben, die beim Entschlüsseln der Nachricht helfen.
Der erste Schritt beim Entschlüsseln der Nachricht besteht darin, die Verschiebung aus dem Verschlüsselungsprozess rückgängig zu machen, indem du die Bits wieder nach rechts verschiebst.
Es folgen weitere Schritte im Entschlüsselungsprozess, die davon ausgehen, dass von der linken Seite 0 eingefügt werden.
Implementiere die Funktion shiftBack, die eine Anzahl von Stellen zum Verschieben und einen Wert entgegennimmt und die Verschiebung durchführt.
shiftBack 2 42 --> 10
Als Nächstes gibt es einige Bits, die auf 1 gesetzt werden müssen.
Implementiere die Funktion setBits, die eine Maske und einen Wert entgegennimmt und das Ergebnis davon zurückgibt, die Bits im Wert auf 1 zu setzen.
Ein Bit aus dem Wert sollte auf 1 gesetzt werden, wenn das Bit in der Maske ebenfalls 1 ist.
Alle anderen Bits sollten unverändert bleiben.
setBits 66 212 --> 64
Einige Bits werden während der Verschlüsselung umgedreht. Sie müssen zurückgedreht werden, um die Nachricht zu entschlüsseln.
Implementiere die Funktion flipBits, die eine Maske und einen Wert entgegennimmt.
Die Maske gibt an, welche Bits im Wert umgedreht werden sollen.
Wenn das Bit in der Maske 1 ist, wird das Bit im Wert umgedreht.
Alle anderen Bits bleiben unverändert.
flipBits 23 157 --> 138
Es gibt auch bestimmte Bits, die immer zu 0 entschlüsselt werden.
Implementiere die Funktion clearBits, die eine Maske und einen Wert entgegennimmt.
Die Bits im value sollten auf 0 gesetzt werden, wo das Bit in der Maske 1 ist.
Alle anderen Bits sollten unverändert bleiben.
clearBits 2 15 --> 13
Jetzt, da du alle Funktionen hast, die du brauchst, kannst du die Nachricht deines Freundes entschlüsseln.
Implementiere die Funktion decrypt, die die folgenden Operationen ausführt:
decrypt 380182 --> 11840
Bitte implementiere decrypt mit allen Funktionen, die du in den vorherigen Aufgaben implementiert hast.
Melde dich bei Exercism an, um Elm mit 28 Konzepte110 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.