# 2023q1 Homework2 (quiz2) contributed by < `ShallowFeather` > ## 測驗 1 ```c uint64_t next_pow2(uint64_t x) { x |= x >> 1; x |= x >> 1; x |= x >> 1; x |= x >> 1; x |= x >> 1; x |= x >> 1; x |= x >> 1; x |= x >> AAAA; x |= x >> 16; x |= x >> BBBB; return CCCC; } ``` AAAA 為 8 BBBB 為 32 CCCC 為 x + 1 也能將該段 code 縮短成 ```c uint64_t next_pow2(uint64_t x) { x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x |= x >> 32; return x + 1; } ``` 可以這樣運算是因為可以知道當右移一位並做 `|` 運算後會將他的右項倍增 就像是 1000000 在跟 0100000 `|` 後會是 1100000 也因此可以直接將下一次運算時直接右移 2 位來節省運算次數。 以此類推。 ## 測驗 2 ```c int concatenatedBinary(int n) { const int M = 1e9 + 7; int len = 0; /* the bit length to be shifted */ /* use long here as it potentially could overflow for int */ long ans = 0; for (int i = 1; i <= n; i++) { /* removing the rightmost set bit * e.g. 100100 -> 100000 * 000001 -> 000000 * 000000 -> 000000 * after removal, if it is 0, then it means it is power of 2 * as all power of 2 only contains 1 set bit * if it is power of 2, we increase the bit length */ if (!(DDDD)) len++; ans = (i | (EEEE)) % M; } return ans; } ``` DDDD 為 i & (i - 1) EEEE 為 ans << len `i & (i - 1)` 此操作將會移除最右邊的那個 `1` 那如果說他是 `2` 的冪次方就需要多一個 `bit` 來存他的二進位數值,因此將 `len++` 並在後面左移 len 位數並將 `i` 附加在 `ans` 右側 ## 測驗 3 ## 測驗 4 ```c bool is_pattern(uint16_t x) { const uint16_t n = EEEE; return (n ^ x) < FFFF; } ``` EEEE = -x FFFF = x 此題目要求為 確認 x 的 binary 是否符合在最右邊的 `1` 後皆為 `0` -x 為 x 的二補數 EX: 如 x = 1100 0000 0000 0000 則他的補數為 0100 0000 0000 0000 因此並不會比 x 還要大 不過如果 x 為 1100 0000 0000 0001 其補數則為 0011 1111 1111 1111 則必定大於 x