整数除法的表达式取值¶
整数除法的取整方向¶
C99 起, 两个整数做 / 运算时, 结果是代数商去掉小数部分, 在数轴上朝 0 靠拢. 标准脚注里把这称为 truncation toward zero (向零截断).
| 表达式 | 代数商 | / 的结果 | Floor | Ceiling |
|---|---|---|---|---|
5 / 2 | 2.5 | 2 | 2 | 3 |
(-5) / 2 | -2.5 | -2 | -3 | -2 |
5 / (-2) | -2.5 | -2 | -3 | -2 |
(-5) / (-2) | 2.5 | 2 | 2 | 3 |
规律可以概括为:
-
商为正 (两操作数同号) → 向零截断与 Floor 一致
-
商为负 (两操作数异号) → 向零截断与 Ceiling 一致
-
能整除时, 三者相同
常见误解
整数除法既不是 Floor 也不是 Ceiling. 决定它与谁等价的是商的符号, 不是单个操作数的正负.
例如 (-5) / (-2) 的两个操作数都为负, 但商为正, 结果 2 仍是 Floor, 不是 Ceiling. 因此不能说「操作数为正时相当于 Floor, 为负时相当于 Ceiling」.
C89 中, 若有一方为负数, 取整方向是implementation-defined; 现代编译器普遍遵循 C99 的向零截断.
正整数情形¶
当 x 和 n 均为正整数时, 商恒为正, 向零截断恰好就是 Floor:
x / n // Floor. 例: 17 / 4 == 4
Ceiling 则要求「有余数就进 1, 能整除则不变」, 不能单靠 / 完成. 常见写法有三种:
x / n + x % n // 写法 1: 利用余数作进位标志
(x + n - 1) / n // 写法 2: 先凑整再除
x / n + (x % n != 0) // 写法 3: 显式判断
| x | n | x/n (Floor) | x/n + x%n | (x+n-1)/n |
|---|---|---|---|---|
| 17 | 4 | 4 | 4 + 1 = 5 | 20 / 4 = 5 |
| 16 | 4 | 4 | 4 + 0 = 4 | 19 / 4 = 4 |
当 x 不能被 n 整除时, 余数 x % n 落在 1 … n-1, 作为整数加到商上恰好等于 +1. 能整除时余数为 0, 不加 1.
这一写法仅适用于 x, n 均为正整数. 操作数可能为负时, 需要另写逻辑.
Example
例如, 假设变量x和n是两个正整数,我们知道x/n这个表达式的结果要取Floor,例如x是17,n是4,则结果是4。如果希望结果取Ceiling应该怎么写表达式呢?例如x是17,n是4,则结果是5;x是16,n是4,则结果是4。
就可以通过下面的程序解决:
#include <stdio.h>
int main(){
int x = 17;
int n = 4;
printf("Floor of x/n: %d\nCeiling of x/n: %d\n", x/n, x/n + x%n);
return 0;
}
运行输出:
Floor of x/n: 4
Ceiling of x/n: 5
若把x的值替换成16, 由于x%n的值为0, 因此就不会产生ceiling的值了:
Floor of x/n: 4
Ceiling of x/n: 4