# 2018q1 第 2 週測驗題
---
### 測驗 `一`
![](https://i.imgur.com/Mp0cHII.jpg)
請完成下方程式碼,依循 IEEE 754 單精度規範,輸出 $2^x$ 的浮點數表達法,而且考慮兩種狀況:
* 當 $x$ 過小的時候,回傳 $0.0$
* 當 $x$ 過大的時候,回傳 $+\infty$
注意:這裡假設 `u2f` 函式返回的浮點數值與其無號數輸入有著相同的位數,也就是至少 32-bit
```Clike
#include <math.h>
static inline float u2f(unsigned int x) { return *(float *) &x; }
float exp2_fp(int x) {
unsigned int exp /* exponent */, frac /* fraction */;
/* too small */
if (x < 2 - pow(2, Y0) - 23) {
exp = 0;
frac = 0;
/* denormalize */
} else if (x < Y1 - pow(2, Y2)) {
exp = 0;
frac = 1 << (unsigned) (x - (2 - pow(2, Y3) - Y4));
/* normalized */
} else if (x < pow(2, Y5)) {
exp = pow(2, Y6) - 1 + x;
frac = 0;
/* too large */
} else {
exp = Y7;
frac = 0;
}
/* pack exp and frac into 32 bits */
return u2f((unsigned) exp << 23 | frac);
}
```
==作答區==
Y0 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y1 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y2 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y3 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y4 = ?
* `(a)` 20
* `(b)` 21
* `(c)` 22
* `(d)` 23
* `(e)` 24
* `(f)` 25
* `(g)` 26
* `(h)` 27
Y5 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y6 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
Y7 = ?
* `(a)` 0x00
* `(b)` 0xF0
* `(c)` 0xFA
* `(d)` 0xFB
* `(e)` 0xFC
* `(f)` 0xFD
* `(g)` 0xFE
* `(h)` 0xFF
Reference:
* [Exploration of the IEEE-754 Floating Point Standard](http://blog.ruofeidu.com/exploration-ieee-754-floating-point-standard/)
[90]
:::info
延伸題: 給定一個單精度的浮點數值,輸出較大且最接近的 $2^x$ 值,需要充分考慮到邊界
:::
---
### 測驗 `二`
考慮以下程式碼對一個浮點數進行 `* 0.5` 的操作,補完程式:
```Clike
typedef unsigned int float_bits;
float_bits float_x0_5(float_bits f) {
unsigned sig = f >> 31;
unsigned rest = f & 0x7FFFFFFF;
unsigned exp = f >> 23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
/* NaN or INF */
if (exp == A0) return f;
/* round to even. Last 2 bits of frac are considered:
* 00 => 0 just >> 1
* 01 => 0 (round to even) just >> 1
* 10 => 1 just >> 1
* 11 => 1 + 1 (round to even) just >> 1 and plus 1
*/
int addition = (frac & 0x3) == 0x3;
/* Denormalized */
if (exp == 0) {
frac >>= A1;
frac += addition;
/* Normalized to denormalized */
} else if (exp == 1) {
rest >>= A2;
rest += addition;
exp = rest >> A3 & A4;
frac = rest & 0x7FFFFF;
/* Normalized */
} else {
exp -= A5;
}
return sig << A6 | exp << 23 | frac;
}
```
==作答區==
A0 = ?
* `(a)` 0x00
* `(b)` 0xF0
* `(c)` 0xFA
* `(d)` 0xFB
* `(e)` 0xFC
* `(f)` 0xFD
* `(g)` 0xFE
* `(h)` 0xFF
A1 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
A2 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
A3 = ?
* `(a)` 20
* `(b)` 21
* `(c)` 22
* `(d)` 23
* `(e)` 24
* `(f)` 25
* `(g)` 26
* `(h)` 27
A4 = ?
* `(a)` 0x00
* `(b)` 0xF0
* `(c)` 0xFA
* `(d)` 0xFB
* `(e)` 0xFC
* `(f)` 0xFD
* `(g)` 0xFE
* `(h)` 0xFF
A5 = ?
* `(a)` 0
* `(b)` 1
* `(c)` 2
* `(d)` 3
* `(e)` 4
* `(f)` 5
* `(g)` 6
* `(h)` 7
A6 = ?
* `(a)` 31
* `(b)` 30
* `(c)` 29
* `(d)` 28
* `(e)` 27
* `(f)` 26
* `(g)` 25
* `(h)` 24
Reference:
* [Floating Point Multiplication](https://www.doc.ic.ac.uk/~eedwards/compsys/float/)
[95]
---
### 測驗 `三`
考慮到某些實數的二進位表示形式如同 $0.yyyyy...$ 這樣的無限循環小數,其中 $y$ 是個 $k$ 位的二進位序列,例如 $\frac{1}{3}$ 的二進位表示為 $0.01010101...$ (y = `01`),而 $\frac{1}{5}$ 的二進位表示為 $0.001100110011...$ (y = `0011`),考慮到以下 y 值,求出對應的十進位分數值。
* y = `010011` => $\frac{19}{X1}$
* y = `101` => $\frac{5}{X2}$
* y = `0110` => $\frac{2}{X3}$
X1 = ?
* `(a)` 11
* `(b)` 23
* `(c)` 63
* `(d)` 97
* `(e)` 57
* `(f)` 31
* `(g)` 5
* `(h)` 13
X2 = ?
* `(a)` 17
* `(b)` 19
* `(c)` 13
* `(d)` 11
* `(e)` 3
* `(f)` 7
* `(g)` 23
* `(h)` 97
X3 = ?
* `(a)` 23
* `(b)` 19
* `(c)` 17
* `(d)` 13
* `(e)` 11
* `(f)` 7
* `(g)` 5
* `(h)` 3
Reference:
* [Binary Fractions](https://www.electronics-tutorials.ws/binary/binary-fractions.html)
[83]
---
### 測驗 `四`
在 [你所不知道的C語言: 遞迴呼叫篇](https://hackmd.io/s/rJ8BOjGGl) 提到以下程式碼:
```Clike
#include <stdio.h>
int p(int i, int N) {
return (i < N && printf("%d\\n", i)
&&!p(i + 1, N)) || printf("%d\\n", i);
}
int main() { return p(1, 10) && printf("\\n"); }
```
預期會得到以下輸出:
```
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 ->
```
注意 `10` 只會出現一次。請填補下方程式碼,使得輸出為 `1 -> 2 -> 3 -> 4 -> 5 ->`,並且包含換行符號 (`\n`)
```Clike
#include <stdio.h>
int p(int i, int N) {
return (i < N && printf("%d -\> ", i)
&& Q1(i + Q2, N + Q3));
}
int main() { return p(1, 10) && printf("\\n"); }
```
提示: Q1 是函式名稱,可能包含 `~` (bitwise NOT) 操作,Q2 和 Q3 是有號整數
==作答區==
Q1 = ?
* `(a)` p
* `(b)` ~p
Q2 = ?
* `(a)` -5
* `(b)` -4
* `(c)` -3
* `(d)` -2
* `(e)` -1
* `(f)` 0
* `(g)` 1
* `(h)` 2
* `(i)` 3
* `(j)` 4
Q3 = ?
* `(a)` -5
* `(b)` -4
* `(c)` -3
* `(d)` -2
* `(e)` -1
* `(f)` 0
* `(g)` 1
* `(h)` 2
* `(i)` 3
* `(j)` 4