# 2020q3 Homework5 (quiz5)
contribute by <`hsiehong`>
###### tags: `進階電腦系統理論與實作`
[題目](https://hackmd.io/@sysprog/2020-quiz5)
[TOC]
## 測驗1
浮點數除法
```c=
#include <stdio.h>
#include <stdlib.h>
double divop(double orig, int slots) {
if (slots == 1 || orig == 0)
return orig;
int od = slots & 1;
double result = divop(orig / D1, od ? (slots + D2) >> 1 : slots >> 1);
if (od)
result += divop(result, slots);
return result;
}
```
D1 = `2`, D2 = `1`
* `od` : 判斷 `slot` (除數) 是否為奇數
* 若除數是偶數,則除數和被除數可以同除 2 ,結果是一樣的,即 `orig`/`slot` = $\dfrac{orig}{2}$/$\dfrac{slot}{2}$
* 當除數是奇數時要特別處理,因為呼叫遞迴是 `divop(orig/2, (slot+1)/2)`,因為 `slot` 是奇數。所以 `(slot+1)/2` 也會是整數,但是正確的應該是 `divop(orig/2, slot/2)`,所以 line 9, 10 在做修正,要修正的值是
$\dfrac{orig}{slot}$ - $\dfrac{orig}{slot+1}$ = $\dfrac{orig \times (slot+1)}{slot \times (slot+1)}$ - $\dfrac{orig \times slot}{slot \times (slot+1)}$ = $\dfrac{orig}{slot \times (slot+1)}$
其中 $\dfrac{orig}{slot+1}$ 就是 line8 所得到的 `result`,所以$\dfrac{result}
{slot}$即為要補回去的誤差值
## 測驗2
QQ0 = `0x01000000`, QQ1 = `0x3f000000`, QQ2 = `23`
## **測驗3**
LeetCode [829. Consecutive Numbers Sum](https://leetcode.com/problems/consecutive-numbers-sum/)
給定一正整數 N,問 N 能寫成幾種連續正整數之和
* 根據題目給定算式可以得到 $kx = N - \dfrac{(k - 1)k}{2}$,其中 $\dfrac{(k - 1)k}{2}$ 可以看成是 $0+1+...+(k-1)$,就是求 $k,x$ 正整數解個數,將上式移項可得 $x = \dfrac{N - \frac{k \times (k-1)}{2}}{k}$
* 已知 `x` 是從 `N` 開始,`x += zzz` 對應到就是 $N - \displaystyle\sum_ {i=0}^{k-1}i$,k 對應到 `i` ,從2開始檢查,因為1必有解就是該數本身,可得 zzz = `1 - i`
* 舉例來說,假設 N = 10,i 從 2 開始
| iteration | N(x) | i | x%i | ret |
|:---------:|:----:|:---:|:---:|:---:|
| init | 10 | 2 | - | 1 |
| 1 | 9 | 2 | 1 | 1 |
| 2 | 7 | 3 | 1 | 1 |
| 3 | 4 | 4 | 0 | 2 |
```c=
int consecutiveNumbersSum(int N)
{
if (N < 1)
return 0;
int ret = 1;
int x = N;
for (int i = 2; i < x; i++) {
x += ZZZ;
if (x % i == 0)
ret++;
}
return ret;
}
```
zzz = `1-i`
另解 :
根據式子 $kx = N - \dfrac{k \times (k+1)}{2}$,只要找出 $k$, $x$ 的正整數解即可,還有我們已經知道 k 的範圍 ($k < \sqrt{2N}$),可以減少迴圈要跑的範圍
> question : 範圍應該是 k < $\sqrt{2N+k}$,不太明白為什麼估計值可以省略 k
```c=
int consecutiveNumbersSum(int N)
{
int res = 1;
for (int k = 2; k <= sqrt(N << 1); k++) {
if ((N - ((k * (k - 1)) >> 1)) % k == 0)
res++;
}
return res;
}
```