contributed by <blake11235
>
好東西分享,很完整的HackMD功能介紹
考慮以下程式碼:
其作用為檢查輸入整數是否為 N 的倍數
首先先觀察程式碼
從這段可以得知他是在計算 n 用 binary 表示的話,奇數位與偶數位的 1 的數目。先是判斷最右邊的那位數,看是否為 1 ,接著向右位移再判斷是否為 1 ,一直操作到 n 為 0 ,代表全部計算完畢。
最後將 odd bit count 和 even bit count 的差值再次輸入函式做遞迴,直到數值為 0 或 1 。也就是最終的判斷依據,是看奇數位 1 的數與偶數位 1 的數兩者要一樣。
既然這段程式碼是依據各 bit 在判斷,那麼就把數值列出來啦~
數值 | binary | 奇偶位 1 的數的差值 |
---|---|---|
1 | 0001 | 1 |
2 | 0010 | 1 |
3 | 0011 | 0 |
5 | 0101 | 2 |
7 | 0111 | 1 |
11 | 1011 | 1 |
13 | 1101 | 1 |
搭啦~ 答案很明顯的就是 3 啦~ | ||
因為只有 3 他的奇位 1 的數目和偶位 1 的數目一樣,所以只能選他了。 | ||
若差值是 1 以上的,會再次進入函式遞迴,直到最後的數值是 1 或者 0 。 |
但事情有那麼順利嗎?會不會有除了 3 以外的質數,他的奇位 1 的數目和偶位 1 的數目也一樣,是不是就爆炸了?那麼我們就來證證看囉!
首先,這個題目讓我想到了一個經典個國中數學題目:如何判斷一個數 3 的倍數?
只需要把每個位數的值都加起來,如果為 3 的倍數的話,那麼此數就是 3 的倍數。
推導方法很簡單,這裡就有點了的講…
那麼就從那個觀念延伸,來這提證明。
假設一個二進位的數值 ABCDEFGH ,代表的是
是 3 的倍數
所以只要判斷 也要是 3 的倍數就好了
可能是 3、6、9 …等等,再把數值代進迴圈,直到最後奇偶位數相差為 0 ,便知道此數是 3 的倍數
針對其他質數判斷是否為其倍數,2 和 5 較為簡單,就不多說了,那麼就想針對 7、11、13 做研究
再次回想起國中數學~~
目標,只使用加減法位移與迴圈
針對一個數於乘於 7 直式乘法,可以觀察到一個有趣現象
也就是說,把一個數除以 7 ,就是把最後一位數拿去減倒數第三位、倒數第二位和倒數第一位,減完之後數值向右位移,然後回傳給函式繼續進行,直到除了後三位的其他位數都是 0 ,最後再判斷數值是否為 7 。
既然都打出程式了,那麼就來比賽一下,看看是否有比 mod 運算還快,不然而外想到的這種作法沒有比較快,內心會很挫折。
所以阿我用了 clock() 來算一下時間,跟 mod 來比賽看看
結論是…
我輸了
好吧…先做 11 的倍數,不然做不完啦…
11 的倍數也可以用類似於 7 的倍數的方法,只是改變了一點數值。
但是,這個方法他的運算時間,比 mod 慢更多,差到了100倍左右…
想一個比 mod 慢的程式有屁用<bye94046165
>
也是可以用一樣的手法但是速度一樣慢…
所以,強者我室友e94046165
看了我的 code 叫我把函式遞迴改成 while() 迴圈,順便嘴我的資料結構…
結果,速度快的幾乎跟 mod 一樣了!!
以類似 CS:APP 3/e 第 80 頁針對 8 位元浮點格式的示例,擴充至單精度浮點數
位表示(b x x b) | 指數 | 小數 | 值 | 描述 |
---|---|---|---|---|
bin hex hex bin | e, E, 2E | f, M | V, 十進位 | |
0 00 00000 000 | 0, -126, 2-126 | 0, 0 | 0, 0.0 | 零 |
0 00 00000 001 | 0, -126, 2-126 | 2-23, 2-23 | 2-149, 0.00.. | 最小 denormalized |
… | … | … | … | denormalized |
0 00 11111 111 | 0, -126, 2-126 | 2-1+2-2…+2-23, 2-1+2-2…+2-23 | … | 最大 denormalized |
0 01 00000 000 | 1, -126, 2-126 | 0, 1 | 2-126, 0.00… | 最小 normalized |
0 01 00000 001 | 1, -126, 2-126 | 2-23, 1+2-23 | 2-126+2149, 0.00… | normalized |
… | … | … | … | normalized |
0 fe fffff 111 | 254, 127, 2127 | 2-1+2-2…+2-23, 1+2-1+2-2…+2-23 | … | 最大 normalized |
0 ff 00000 000 | … | … | … | 正無限大 |
在來看題目:
(x < 2 - pow(2, 7) - 23)
(x < 2 - pow(2, 7))
1 << (x - (2 - pow(2, 7) - 23))
(x < pow(2, 7))
exp = pow(2, 7) - 1 + x
0xff
給定一個單精度的浮點數值,輸出較大且最接近的 2x 值,需要充分考慮到邊界
原來是針對原本的題目做反向操作阿,研究了一下,就用 bits 來操作吧
首先針對所得到的浮點數做分類:
完成了…嗎?
原來, float 不能做 bitwise 的運算阿!我真的現在才知道
于是乎,我想到了一招,用 pointer
意思就是透過轉換位址的型態,將位址傳給 type size 一樣的 unsigned int ,在對它取值,這樣就可以對 unsigned int 做 bitwise 運算了
最後我再多計算輸出 2x 與原本浮點數的差值
再啦幹
e94046165…謝謝…
blake11235
延續 從 的運算談浮點數,假設 double 為 32-bit 寬度,考慮以下符合 IEEE 754 規範的平方根程式,請補上對應數值,使其得以運作:
乾這題好難,本來想偷偷看有誰有做這題的,結果沒有…
首先先解決那五格填空該填入什麼
可以觀察出此段程式碼要判斷是否為 INF 或 NAN ,而判斷標準就是數字 exp 的部份皆為 1 ,因此 KK2 為 0x7ff00000 , mask 的部份就是取 ix0 的 62~52 位數,所以 KK1 也是 0x7ff00000
程式碼後面的註解都說了要 unbias 也就是將偏置移動回來,對 double 雙精度而言 Bias = 2k-1 - 1 = 1023
其實這題我不太懂…
最後這段,是要把 m exponent 放入 ix0 裡面,而針對 double 他的 exp 是在 62~52 位元,所以需要向左位移 51-32+1=20 位
sqrt(NaN) = NaN, sqrt(+INF) = +INF, sqrt(-INF) = sNaN
因此使用 x * x + x 來表示,參考這裡不太清楚為何能讓 透過 (x - x) / (x - x); 使得 sqrt(-ve) = -NaN ,是否因為產生了 -0/-0 ?
感覺不難,只需要把數值改成對應 float 格式就好。