取整技巧
上取整
对于上取整,有 \(\lceil \frac a b \rceil = \lfloor \frac {(a + b - 1)} {b} \rfloor\),即 ceil(1.0 * a / b) = (a + b - 1) / b
。
上取整的本质就是:余数不为 \(0\),则结果加 \(1\);余数为 \(0\),结果不变。因为 C++ 的除法(本质上是向 \(0\) 除法)在正数的情况下就是向下除法。因此我们可以直接加上 \(b - 1\),那么当余数 \(r\) 大于等于 \(1\) 时,因为 \(b - 1 \ge r \ge 1\),所以 \(2b \ge 2(b - 1) \ge r + b - 1 \ge b\),所以 \(\lfloor \frac r b \rfloor = 1\)。通过这种方法,可以避免使用 \(ceil\),更方便一点。
四舍五入
C++ 中四舍五入可以使用 \(round\) 函数,也可以直接使用整数代替。有round(1.0 * x / y) = (a + b / 2) / b
。
证明:设 \(r = a \bmod b,\ k = \lfloor \frac a b \rfloor\),对于四舍五入,实际上就是当 \(r \div b >= \frac 1 2\) ,即 \(r \ge \frac 1 2 b\) 时,那么结果加一,否则结果不变。因为 \(b - 1 \ge r \ge \frac 1 2 b\),所以 \(2b > b - 1 + \frac 1 2 b \ge r + \frac 1 2 b \ge b\),所以当 \(r \ge \frac 1 2 b\) 时,\(\lfloor \frac{r + \frac 1 2 b}{b} \rfloor = 1\)。 得证。