筆記:Bits

有兩個符號讓我很好奇: >><<。我就問了 ChatGPT 是什麼意思。經過一陣對談後,我想我可以彙整一下了。

TL;DR

如果想快速記憶的話:

1 << 1 // 2
1 << 2 // 4
1 << 3 // 8
1 << 4 // 16
1 << 5 // 32
1024 >> 1 // 512
1024 >> 2 // 256
1024 >> 3 // 128
1024 >> 4 // 64
1024 >> 5 // 21

先決知識:二進位

在讀這個筆記前,你需要知道二進位是什麼:二進位是一種以 0 與 1 還有位數來標記數字的方法。因為 0 與 1 可以轉為低電壓與高電壓,因此要以電力作為動能的電腦去算術,就需要把數字弄成二進位。每次進位是前一位數乘以二。

比方說十進位的 9 換算成二進位就會是 1001:

8421 => DEC
----
1001 => BIN

因為 (8 * 1) + (4 * 0) + (2 * 0) + (1 * 1) 是 9,所以十進位的 9 換算成二進位就會是 1001。

你可以把作業系統內建的計算機程式,切到程式員模式後用 DEC 輸入十進位,接著與 BIN 比照看看。

<<

<< 是把二進位數往左推幾進位,或換句話說,在數字的後面多加幾個 0。就從 9 << 3 開始吧。 9 << 3 的答案是 72。為什麼?

9 換成二進位的話就是 1001。現在, 9 << 3 下的指令就變成:「我要把 1001 往左推 3 個位數」、或是「我要給 1001 後面多 3 個 0」。

"1001" + "000" 會是什麼?1001000?那怎麼換算呢?

(64 * 1) + (32 * 0) + (16 * 0) + (8 * 1) + (4 * 0) + (2 * 0) + (1 * 0) 就是 72,所以答案就 72 啦。

所以 1 << 10 會是什麼呢?因為 "1" + "0000000000" => "10000000000" 換成十進位是 1024,所以答案是 1024。

>>

那所以反過來說,>> 就是給數字前面多幾個 0 囉? 9 >> 3 會是什麼? "000" + "1001" => "0001001"?有意義嗎?

噢,不對

>> 要做的是給二進位數字,往右推幾個位數。

一樣從 9 >> 3 開始吧。1001 如果把這數字往右推,會發生什麼事呢?同樣位數的話就會變成 0001:原本的 001 早就被推掉了,所以答案是 1。

反過來說, 2048 >> 5 呢?
直接用計算機吧。

  1. 2048 的二進位為 "100000000000"
  2. "100000000000" 往右推 5 個: "000001000000"
  3. "000001000000" 的十進位為 64
  4. 所以 2048 >> 5 是 64

原始對話

Tell me, how 9 << 3 is 72?


The expression 9 << 3 is a bitwise left shift operation. Here's how it works: The binary representation of decimal 9 is 1001. When you shift it to the left by 3 positions, you get:

1001 << 3 = 1001000

In decimal, 1001000 is 72. Therefore, 9 << 3 equals 72. The value is obtained by multiplying the original value (9) by 2 to the power of the shift amount (3). Mathematically:

9 << 3 = 9 * 2^3 = 9 * 8 = 72


Let me repeat:

  1. When 9 << 3, "9" in decimal will convert to "1001" in a binary
  2. Then "3", will add a binary "1" and two binary "0" like: "100".
  3. Add "100" to "1001" which is "1001001".
  4. Convert a binary "1001001" to decimal "72".

Am I right?


I appreciate your attempt to break it down, but there's a small mistake in step 2. When you perform a left shift by 3 positions, you are not adding binary digits to the original binary representation. Instead, you're shifting the existing bits to the left.

Let me correct the steps:

  1. The decimal number 9 is represented in binary as "1001."
  2. Left shift the bits by 3 positions: "1001" becomes "1001000."
  3. Convert the binary "1001000" to decimal, which is 72.

So, your final representation is correct, but the process of obtaining it involves only shifting the existing bits to the left, not adding new binary digits.


Now again with 3 << 3:

  1. Convert the decimal 3 to binary "11".
  2. Add three "0" after "11", which is "11000".
  3. Convert the binary "11000" to decimal 24.

Right?


Almost correct, but there's a small mistake in step 2. When you perform a left shift by 3 positions, you are not adding three "0"s after "11." Instead, you are shifting the existing bits to the left.

Here's the correct breakdown:

  1. The decimal number 3 is represented in binary as "11."
  2. Left shift the bits by 3 positions: "11" becomes "11000."
  3. Convert the binary "11000" to decimal, which is 24.

So, your final representation is correct, and the process involves shifting the existing bits to the left, not adding new binary digits.


While 1 << 3 turns to "1000" in binary and converts to 8, how about 1 >> 3? Will it turn to "0001" in binary? 1?


The 1 >> 3 operation is a right shift operation. Let's break it down:

  1. The binary representation of 1 is 0001.
  2. Right shift the bits by 3 positions: 0001 becomes 0000.

So, 1 >> 3 results in 0000 in binary, which is 0 in decimal. Right shifting a number by n positions is equivalent to dividing the number by 2^n and discarding the remainder. In this case, 1 >> 3 is equivalent to 1 / 2^3, which is 1 / 8, resulting in 0.125, but since we're working with integers, the result is 0.


So how about 10 >> 2? Turns 1010 (10) into 0010 because it shifts two 0?


Exactly. Let's break it down:

  1. The binary representation of 10 is 1010.
  2. Right shift the bits by 2 positions: 1010 becomes 0010.

So, 10 >> 2 results in 0010 in binary, which is 2 in decimal. Right shifting the bits by 2 positions effectively divides the number by 2^2, which is 4.


I found an interesting tendency:

1 << 1 // 2 1 << 2 // 4 1 << 3 // 8 1 << 4 // 16 1 << 5 // 32

And:

1024 >> 1 // 512 1024 >> 2 // 256 1024 >> 3 // 128 1024 >> 4 // 64 1024 >> 5 // 21

Exactly how the bitwise operators work, right?


Yes, that's correct! The left shift (<<) operation effectively multiplies the original number by 2 raised to the power of the shift amount, and the right shift (>>) operation divides the original number by 2 raised to the power of the shift amount.

In your examples:

For left shift (<<):

For right shift (>>):

So, your observations are consistent with the behavior of bitwise left and right shift operators.