contributed by < DokiDokiPB
>
1
取 EXP1 為 a & b & 1
(a >> 1) + (b >> 1)
會無條件捨去二進位中最低位元的位數,但若 a 與 b 在最低位加法時進位,則(a >> 1) + (b >> 1)
需再加上 1
以數位邏輯電路中, 取得進位數值的運算為(a & b)
表示當前下個 的數值,即上圖中的
取 EXP2 為 a & b
取 EXP3 為 a ^ b
在數位邏輯中, a + b
可以用表示(a ^ b) + ((a & b) << 1)
(a + b) / 2
相當於 ((a ^ b) + ((a & b) << 1)) >> 1
= (a ^ b) >> 1 + (a & b)
2
取 EXP4 為 a ^ b
取 EXP5 為 a <= b
若只單獨觀察 a ^ ...
形式,可以推導
a <= b
,則回傳的形式應為:a ^ a ^ b = b
a > b
,則回傳的形式應為:a ^ 0 = a
若 a <= b
成立,表示 -(a <= b)
的數值為-1
,在二的補數系統中,表示0xFFFFFFFF
。最終取得a ^ a ^ b = b
若 a <= b
不成立,表示 -(a <= b)
的數值為0
,在二的補數系統中,表示0x00000000
。最終取得a ^ 0 = a
3
其等價實作
取 COND 為 v
取 RET 為 u << shift
直接運算一次:
對應測驗題中原本 的程式碼, while loop 的中止條件為: v
= 0
,推導出等價實作的 while loop 的中止條件也為v
,因此取 COND 為 v
在題目敘述中
If x and y are both even, gcd(x, y)= 2 * gcd(x, y) because 2 is a common divisor. Multiplication with 2 can be done with bitwise shift operator.
因此 shift
的作用為預先將 2 公因數提出,最後再做 bitwise operation 回去。
在等價實作的程式碼中,都是對 2 預先做處理,其餘運算事實上與原本的 實作相同。
節錄自 lib/math/gcd.c
在程式碼第 3 ~ 5 行中,r
為 a
與 b
的 2 的冪共同因數,可得
在測驗
1
的延伸閱讀 Introduction to Low Level Bit Hacks #7. Isolate the rightmost 1-bit.,可以得知在二的補數下,r &= -r
取得最低位元的 1 的位置
在程式碼第 6 行中,已知 r
為 a
與 b
最大 2 的共同因數,將 b
多餘的 2 的冪移除。同理在 for loop 中,也將 a
的多餘的 2 的冪移除。
因此在接下來的程式碼中,假設a
= 與 b
= ,其中 m, n
為奇數, r
為 2 的冪
在程式碼第 26 ~ 27 行中, a -= b
必為 r
的倍數,且 (m - n)
必為偶數,必定多出至少一個 2 的冪,可以 a >>= 1
在程式碼第 28 ~ 30 行中,可以簡單用例子說明:假設 a
= , b
= ,若不執行if(a & r) a += b
,會得到 a
= ,這樣 a
不為 r
的整數倍數。 已知 ,透過加回一個 b
不影響結果。
並且因為 a += b
必定產生新的 2 的冪,透過 a >>= 1
移除。
事實上移除第 28 ~ 30 行並不影響結果,在下一個 for loop 中,
a
多餘的 2 的冪會被移除。
4
以及改寫的程式碼
5
取 PPP 為 pos--
取 MMM 為 list_add
取 EEE 為 &(heads + (remainder % size ))
LeetCode 題目敘述為:
numerator
(分子)與denominator
(分母),輸出它的小數。以這樣形式的輸入必為有理數,可能是循環小數或是有限小數。在此可能實作中,先做一次整數除法後,得到 division
與remainder
division
便是小數點前的整數部位remainder
便是小數點後的部位每一次 for loop ,計算小數點後幾位的數字,並且計算remainder
。而中止條件為:
0
,表示此小數為有限小數(
與)
以 337 / 333
為例:
因此可以取 PPP 為 pos--
解答。
在可能實作的程式碼中,使用 hashmap 的方式儲存 remainder,共有 1333 個 index,並使用 Chaining 的方式解決 Collision。可以得出其 hash function 為
因此可以推導出 EEE 為 &(heads + (remainder % size ))
6
取 M 為 _h
取 X 為 0
My Linux System got broken when I test with the following code, using gcc main.c; ./a.out
command.
It is kinda fun.
7
取 KK1 為 div3
取 KK2 為 div5
取 KK3 為 div3 << 2
列出其增值表
div3 | div5 | (2 << KK1) << KK2 | KK1 | KK2 |
---|---|---|---|---|
0 | 0 | 2 | 0 | 0 |
0 | 1 | 4 | 0 | 1 |
1 | 0 | 4 | 1 | 0 |
1 | 1 | 8 | 1 | 1 |
因此取 KK1 為 div3
, KK5 取 div5
。兩者答案可以對調。
原題目
strncpy(fmt, &"FizzBuzz%u"[(9 >> div5) >> (KK3)], length);
會令輸出產生 u
而非 %u
,因此改為
strncpy(fmt, &"FizzBuzz%u"[(8 >> div5) >> (KK3)], length);
考慮 strncpy 複製的範圍,列出其增值表
div3 | div5 | 8 >> div5 >> (KK3) | 預期的 KK3 |
---|---|---|---|
0 | 0 | 8 | 0 |
0 | 1 | 4 | 0 |
1 | 0 | 0 | 4 |
1 | 1 | 0 | 4 |
可以發現 KK3 數值一直為 div3 的四倍,因此,取 div3 << 2