or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
2018q1 Homework2
contributed by <
e94046165
>重做前三周測驗題
第 1 週測驗題_測驗
1
題目如下:
其作用為檢查輸入整數是否為 N 的倍數,那麼 N 為多少?
想法 & 思考
最一開始看到這段程式碼時,腦海中第一個浮現的念頭是 N = 11,會有這樣的想法是因為看到程式碼中比對 奇偶數位 ,而在十進位中,判斷某數是否為11的倍數方法如下:
將奇偶數位數字分別相加後,兩者相減mod11 == 0 則為11 的倍數,下面是舉例。
顯然我忽略了要以二進位的角度去思考,所以這題在第一次作答的時候我選錯了。這題的答案應該是 N = 3 ,但答對此題同學在上台講解的時候說了:
我認為這樣的講法是不夠嚴謹的,接著我將試著以數學歸納法作證明。
數學歸納法
這邊先簡單的解釋數學歸納法:
定義 from wiki
而更容易理解的解釋方法是
證明
試證:所有 3 的倍數,以二進位表示時奇偶位
1
數量相等3 = 011 奇偶數位皆有一個 1,3 為 3 的倍數
假設成立
1
個數相等,分別考慮以下兩種情況:(以下進位皆以二進位為主)m = …00 奇偶數位的
1
數量相等m + 3 = …11 奇偶數位的
1
數量仍相等––>符合命題:m + 3 是三的倍數且奇偶位
1
數量相等m = …0001
m + 3 = …0100 奇偶數
1
個數與原來相同,命題成立m = …0101
m + 3 = …1000 奇偶數
1
個數改變,命題不成立…?由上列證明可得知,
命題:所有 3 的倍數,以二進位表示時奇偶位
1
數量相等是有缺陷的,但這個缺陷來在於我沒有看懂程式碼,還是程式碼寫錯了呢?
測試&重讀程式碼
若是程式碼錯了,那麼應該沒辦法判斷 168 是三的倍數,理由如下:
165 = 10100101
168 = 10101000 奇偶數
1
個數不相等但由上面的測試結果可發現,這個 function 可以正確的判斷
在重新檢視程式碼後,才發現是我忽略了最後那行遞迴呼叫:
當奇偶數位
1
不相等時,會遞迴呼叫,直至得到 0 或 1 為止。也就是說,如果奇偶數位的1
個數差是三的倍數,依然能判斷出它是三的倍數。因此,原假設應修正成:
所有奇偶數位
1
個數相等的數,皆為三的倍數但三的倍數,可能為奇偶數位
1
個數差為 0 或 3n 的數現在又遇到同樣的問題,要怎麼證明這個假設在所有情況下都成立呢?
證明
試證:三的倍數,皆為奇偶數位
1
個數差為 0 或 3n 的數基數位的
1
代表 22n 也就是 :1, 4, 16, 64…這些數共同的特色是 3pi+1偶數位的
1
代表 22n+1 也就是 :2, 8, 32, 128…這些數共同的特色是 3qi-1因此可得到,
奇偶數位
1
的個數相等時:代表 3(P+Q) 為三的倍數奇偶數位
1
的個數相差3的倍數:代表 3P+3 or 3Q-3皆為三的倍數p.s. P = Σpi , Q = Σqi
得證假設成立。
延伸問題
試著將 N 改為 5
解釋程式碼
因為 5 的倍數有此特性: 尾數非 0 即 5
因此重複
n 為偶數則 n = n / 2
n 為奇數則 n = n - 5
由最後 n == 5 or n < 5 可判斷 n 是否為 5 的倍數
由於上列解法實在太平庸了,連我自己都覺得跟發廢文沒兩樣,所以決定丟掉再寫些新的。
這段 code 一樣用來判斷輸入 n 是否為 5 的倍數,但是因為這次一次處理兩個 bits 所以速度應該會較前一個快上一些。而且這個概念應該也可以拓展到其他的質數。
概念如下:
假設 n = (abcde)2
則 n = (abc00)2 + (000de)2
= ( (abc)2 << 2 ) + (000de)2
= ( (abc)2 * (5-1)10 ) + (000de)2
= ( (abc)2 * 5 - (abc - de)2
因為(abc)2 * 5 必定為 5 的倍數,所以只要判斷(abc - de)2是否為 5 的倍數就好,這部份可以交給遞迴呼叫來解決,直到得到結果為止。
現在試著將上面的概念拓展到 N = 7
假設 n = (abcde)2
= (ab000)2 + (00cde)2
= ( (ab)2 << 3 ) + (00cde)2
= = ( (ab)2 * 7 + (ab + cde)2
依照上列概念寫出的程式碼如下:
真舒服XD可以看到判斷式有些不一樣,不過應該挺好理解的。
遞迴呼叫至 n <= 7 ,若 n 等於 0 或 7,則為 7 的倍數,其餘則非。
說來慚愧,會有以上的概念並不是我突然靈光一閃,是在搜尋的過程中看到了一篇國小科展…才讓我想起 11 倍數判斷的原理並加以推廣。
太好了,接著你可以繼續想,上面遞迴和 bit-wise 操作可對應到數位邏輯電路是怎麼組合,來練習吧!
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →第 2 週測驗題_測驗
1
題目如下:
請完成下方程式碼,依循 IEEE 754 單精度規範,輸出 2x的浮點數表達法,而且考慮兩種狀況:
注意:這裡假設
u2f
函式返回的浮點數值與其無號數輸入有著相同的位數,也就是至少 32-bit將 Y0 ~ Y7 填入相對應的數值,使得該函式依輸入的 x 輸出 2x 的浮點數值。
想法 & 思考
這段 code 註解清楚的將整個程式依照輸入的 x 值,分成 4 個範圍(與浮點數表示法相呼應):
單精度浮點數表示法,能表現的最小正值為
0 0…0 0…1
也就是 signed bit 為零;
exponent bits 全為零;
fraction 為 2-23
對應到的 2x ,x = 1 -(128 -1) - 23 = 2 - pow(2, Y0) - 23 ==> Y0 = 7
當 x < 這個值時,則使所有 bits 全為 0
這個範圍介於 too small 與 normalized 之間,也就是 exponent bits 全為零,但 fraction 部份不為零的情況。
因此,x 被限制在 x < Y1 - pow(2, Y2) = 2 - pow(2, 7)
在此範圍內 exp 設定成 0;
而 frac 則依照 x 大小被位移
frac = 1 << (unsigned) (x - (2 - pow(2, Y3) - Y4));
這裡可以依最小的 denormalize 值來判斷參數 Y3、Y4
最小值 x = -149 ==> frac = 1
==> -149 - (2 - pow(2, Y3) - Y4)) == 0
==> Y3 = 7, Y4 = 23
單精度浮點數能表示的最大值為 (2−2−23) × 2127 < 2128 因此 x 值必須小於 128 = pow(2, Y5), Y5 = 7
exp = pow(2, Y6) - 1 + x; 為 x 加上 Bias 127
==> Y6 = 7
最後則是輸入的 x 大於單精度能表示的範圍,在此情況下,
exp 被設定為 8 bits 全為 1 ,Y7 = 0xff
延伸問題
延伸題是原本命題的反向,由輸入的浮點數值決定 x。這個功能與原來的程式相比難上不少…原來是想這麼說的,不過突然想起好像一個工具叫作 log?
以下是偷渡 log2 (以二為底) 求 x 的方法,由於題目要求輸出較大且最接近的 2x,所以在得到 log2 的值後,若 x >= 0 則需要加上 1 以符合此要求。
得到 x 值後再進一步用上面的函式測驗 2x 與輸入的 float 的差距。
以下為簡易的測試結果,此結果不考慮使用者輸入過大或過小的正值,或輸入值為負的 error。
從測試結果可看出,當給定一個單精度的浮點數值,輸出的較大且最接近的 2x 值其實與原輸入的浮點數值有不小差異。若移除命題中 較大 的限制,只找出最接近的 2x 值,可使誤差減少。
TODO:
此議題可討論的面向還有很多,例如:
這些額外的議題可能得等我完成其他作業再說…
很好!有幾點可刺激思考:
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →第 2 週測驗題_測驗
3
題目如下:
考慮到某些實數的二進位表示形式如同 0.y y y y y … 0.yyyyy… 這樣的無限循環小數,其中 y 是個 k 位的二進位序列,例如 1 / 3 的二進位表示為 0.01010101… 0.01010101… (y =
01
),而 1./ 5 的二進位表示為 0.001100110011… 0.001100110011…(y =0011
),考慮到以下 y 值,求出對應的十進位分數值。010011
=> 19/X1101
=> 5/X20110
=> 2/X3請分別選出最接近的X1、X2、X3
想法 & 思考
這題在第一次課堂上作答的時候,因為沒想到適當的解法,所以都是用 估計 的:先手算出 y 的十進位小數值,再看和選項中哪個數最接近。
事後回想起來,若將 12 >> 1 = 0.12 、 0102 >> 3 = 0.0102 這樣的概念引入,這題解起來就會快很多。
由於0.yyyy…代表無窮循環小數 ==>
0.yyyy… = (y >> k) + (y >> 2k)… = y * (1 / 2k + 1 / 22k…)公比為 2k無窮級數
= y * (1 /(2k - 1)) k 取決於 y 是幾個 bits
010011
==> y = 19, k = 6 得到 X1 = 26-1 = 63101
==> y = 5, k = 3 得到 X2 = 23-1 = 70110
==> y = 6, k = 4 得到 0.yyyy.. = 6 / (16 - 1) 約分後得 X3 = 5延伸問題
給定的分數 (即 N/M 形式,當 N 和 M 都是正整數),如何轉換成二進位,而且在表達 bit 數量限制的狀況,轉換的誤差是多少?
由於個人覺得浮點數運算十分麻煩,可以的話能不碰就不碰,因此過去 12 小時一直在想,若我們要算 N/M 並且以二進位表示,可不可以不要跟 float 扯上關係。
以下是我得出的結論:
測試結果
結果看起來不錯,不過我到底在寫什麼鳥呢?
以十進位為例:
若本來 2 / 7 的過程是
2 / 7
= 0.2 + (2 - 0.2*7) / 7
= 0.28 + (0.6 - 0.08*7) / 7
…
上列程式碼做的事就是
2 / 7
= 1/10 *(20/7)
= 1/10 *(2 + 6/7)
= 1/10 * 1/10 *(20 + 60/7)
= 1/10 * 1/10 *(28 + 4/7)
…
不斷使被除數進位,直到大於除數,得到一個整數商值後,再重頭做這些動作。而又因為二進位只有 0 與 1 的特性,因此只要做 Shift 與 Sub 就行了,不必考慮 被除數 - 商數 *除數。
程式碼的核心概念如上所述,接下來只要注意以下幾個小細節就好了:
TODO:
將二進位的商數轉換回浮點數,並與浮點數除法比較誤差值。