# 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 作為下一輪輸入 ### 測驗 二 :