# 2025q1 Homework4 (quiz3+4)
contributed by <[`kk908676`](https://github.com/kk908676)>
# 第 3 週測驗題
### 測驗 一 :
#### 參考答案
- AAAA = (n+d-1)/d
- BBBB = 0x7fffffff
- CCCC = n+m
- DDDD = 1
- EEEE = mpi_gcd(rop,op2,r)
### 程式碼運作原理
```c
/* ceiling division without needing floating-point operations. */
static size_t ceil_div(size_t n, size_t d)
{
return (n + d - 1) / d; // ← AAAA
}
```
這是經典的「整數實現的向上除法」,避免使用浮點數:
- 若 n 可被 d 整除則剛好,否則就進一格
- 應用在需要知道`至少要幾格能裝下 n 單位,每格能裝 d 單位`的場景
```c
#define INTMAX 0x7FFFFFFF // ← BBBB,31 bits all 1s
```
由於這個 MPI 實作是以 31-bit 為單位儲存每一段數字(因為乘法可能會進位到第 32 位),所以這個掩碼用來確保每段最大為 2^31 - 1。
```c
for (size_t n = 0; n < op1->capacity; ++n) {
for (size_t m = 0; m < op2->capacity; ++m) {
uint64_t r = (uint64_t) op1->data[n] * op2->data[m];
uint64_t c = 0;
for (size_t k = n + m; c || r; ++k) { // ← CCCC = n + m
if (k >= tmp->capacity)
mpi_enlarge(tmp, tmp->capacity + 1);
tmp->data[k] += (r & INTMAX) + c;
r >>= 31;
c = tmp->data[k] >> 31;
tmp->data[k] &= INTMAX;
}
}
}
```
k是 op1 第 n 位與 op2 第 m 位相乘的 bit 個數
```c
for (size_t i = start; i != (size_t) -1; --i) {
mpi_mul_2exp(r, r, 1); // ← DDDD = 1
if (mpi_testbit(n0, i) != 0)
mpi_setbit(r, 0);
if (mpi_cmp(r, d0) >= 0) {
mpi_sub(r, r, d0);
mpi_setbit(q, i);
}
}
```
每輪都要把 r 乘以 2,並把 n 的第 i 位塞進來。從高位往低位做二進位長除法
```c
void mpi_gcd(mpi_t rop, const mpi_t op1, const mpi_t op2)
{
if (mpi_cmp_u32(op2, 0) == 0) {
mpi_set(rop, op1);
return;
}
mpi_t q, r;
mpi_init(q);
mpi_init(r);
mpi_fdiv_qr(q, r, op1, op2);
mpi_gcd(rop, op2, r); // ← EEEE
mpi_clear(q);
mpi_clear(r);
}
```
這是經典的輾轉相除法(Euclidean Algorithm):
```c
gcd(a, b) = gcd(b, a % b)
```
程式中:
- op1 % op2 → 餘數儲存在 r
- 然後用 op2, r 作為下一輪輸入
### 測驗 二 :