Crystal 提供了位元運算子,可以在二進位層級操作 Int。
Crystal 提供了位移運算子,可以將位元向左(<<)或向右(>>)位移。
<<)左移運算子(<<)會將位元向左位移。
要位移的值放在左邊,要位移的位數放在右邊。
0b0010 << 1
# => 0b0100
0b0010 << 2
# => 0b1000
如果數字是負數,就會改為向右位移。
0b0010 << -1
# => 0b0001
>>)右移運算子(>>)會將位元向右位移。
和左移運算子一樣,要位移的值放在左邊,要位移的位數放在右邊。
0b0100 >> 1
# => 0b0010
0b0100 >> 2
# => 0b0001
同樣地,如果數字是負數,運算子就會改為向左位移。
0b0100 >> -1
# => 0b1000
Crystal 有 3 個二元運算子(&、|、^),以及一個用來執行位元運算的 ~ 運算子。
&)二元 AND 運算子(&)會對兩個值執行位元 AND 運算。
它會把第一個值的每個位元,和第二個值中相同位置的位元做比較。
如果兩個位元都是 1,結果位元就會設為 1,否則設為 0。
0b0011 & 0b1010
# => 0b0010
|)二元 OR 運算子(|)會對兩個值執行位元 OR 運算。
它同樣會比較第一個值的每個位元,和第二個值中相同位置的位元。
只要其中一個位元是 1,結果位元就會設為 1,否則設為 0。
0b0011 | 0b1010
# => 0b1011
^)二元 XOR 運算子(^)會執行位元 XOR 運算。
和位元 AND、位元 OR 運算子一樣,它會把第一個值的每個位元,和第二個值中相同位置的位元做比較。
如果兩者中_只有一個_是 1,結果位元就是 1,否則就是 0。
0b0011 ^ 0b1010
# => 0b1001
~)最後,位元 NOT 運算子(~)會翻轉值的每個位元。
和其他二元運算子不同,這是一元運算子,只對右邊的值運作。
~0b1110_0010
# => 0b0001_1101
有人剛傳了一則帶有重要秘密的訊息給你。 對方不想讓其他人輕易讀到內容,所以這則訊息經過一連串位元操作加密。 你需要寫一個程式來協助解密這則訊息。
解密訊息的第一步,是把加密過程中做的位移還原,也就是把位元往左移回去。 每則訊息需要位移的位數可能不同。
實作 Secrets.shift_back方法,它接受一個值和要往左位移的位數。
Secrets.shift_back(0b0001, 2)
# => 0b0100
下一步是套用位元遮罩,取出特定幾個位元的值。 遮罩的套用方式是對值和遮罩做位元 AND 運算。
實作 Secrets.apply_mask方法,它接受一個值並套用遮罩。
Secrets.apply_mask(0b0110, 0b0101)
# => 0b0100
把位元往左移之後,會多出一些新的 0 位元。 其中有些新的位元需要設成 1。 位元 OR 很適合用來把特定幾個位元設成 1,同時保留其他位元。
實作 Secrets.set_bits方法,它接受兩個值並執行位元 OR。
Secrets.set_bits(0b0110, 0b0101)
# => 0b111
加密過程的其中一個步驟,是對一個雙方講好的值做 XOR。 要還原成原始的值,只要把加密後的值再跟講好的值做一次 XOR 就行了。 不過,因為一場誤會,你的朋友在套用 XOR 之前,先把講好的值的位元翻轉了(也就是對講好的值做了位元 NOT)。
實作 Secrets.reverse_xor方法,它接受加密後的值和講好的值,算出原始的值。
Secrets.reverse_xor(0b1100, 0b0101)
# => 0b(0110)