向上取整的原理
文章目录
- 1. 先解决一个具体问题:
- 2. 把这个过程写成一个“动作”:
- 3. 现在的问题变成了:
- 4. 拆解一下:加上 (盒子容量 – 1) 有什么作用?
- 5. 用更直观的“数轴”想象(不用代码,用文字):
- 6. 如果用生活场景代替:
- 7. 最后,如果还是觉得复杂,可以这样做:
1. 先解决一个具体问题:
你有 10 个鸡蛋,每个盒子最多装 8 个鸡蛋。你需要几个盒子?
你的大脑会这样算:
- 10 ÷ 8 = 1 余 2
- 1 个盒子不够,因为还多 2 个鸡蛋,所以需要再加 1 个盒子。
- 一共 2 个盒子。
这个思考过程里,关键一步是:看有没有余数。有余数,就多要一个盒子。
2. 把这个过程写成一个“动作”:
- 用鸡蛋数 除以 盒子容量,得到一个“商”和一个“余数”。
- 如果余数 > 0,就把商 +1;如果余数 = 0,商不变。
- 最后 商 就是需要的盒子数。
比如:
- 10 个鸡蛋 → 商 1,余 2 → 需要 1+1 = 2 盒
- 16 个鸡蛋 → 商 2,余 0 → 需要 2 盒
3. 现在的问题变成了:
能不能不用看余数,一步就算出需要的盒子数?
可以。这个“一步”的公式就是(鸡蛋数 + 盒子容量 - 1) ÷ 盒子容量(只取整数部分)。
为什么这个公式能“不看余数”就得到正确结果?
4. 拆解一下:加上 (盒子容量 – 1) 有什么作用?
还是用 10 个鸡蛋,每盒 8 个:
- 不加任何东西直接除法:10 ÷ 8 = 1(整数部分) → 错误,因为需要 2 盒。
- 加 7 之后再除: (10+7) ÷ 8 = 17 ÷ 8 = 2(整数部分) → 正确。
为什么加 7(也就是 8-1)?
因为“余数”最大就是 7(当鸡蛋数是 15 时,15÷8=1余7)。
加上 7 以后,原来余数是 1~7 的情况,都会被“推”到下一个整数倍,使得整数部分 +1。
而原来余数是 0 的情况(比如 16),加上 7 变成 23,23÷8=2,整数部分不变(因为没跨过 24)。
所以加 (容量-1) 就是:
- 保证“有余数”的时候,整数部分自动增加 1;
- 保证“没余数”的时候,整数部分不变。
5. 用更直观的“数轴”想象(不用代码,用文字):
想象一条刻度线,刻度是 0, 8, 16, 24, 32……
一个数落在某两个刻度之间。
- 如果它正好落在刻度上(如 16),那么加上 7 后还在同一个格子内(16→23,仍在 16~24 之间),整数部分还是 2。
- 如果它落在两个刻度之间(如 10),那么加上 7 后一定跨过下一个刻度(10→17,超过了 16),整数部分就从 1 变成 2。
“跨过下一个刻度” 所需要的“最小加量”是 1,但最差的情况(离下一个刻度最远的点)需要加 7 才能跨过。
所以为了保证所有情况都能跨过(除了刚好在刻度上的情况),我们就统一加 7——这个数字刚好是“最大距离”。
6. 如果用生活场景代替:
你站在一条路上,路面上每隔 8 米有一个路灯。
你想知道自己走到了第几个路灯区间(从0开始数)。
但你不是从0出发,而是从某个位置出发。
你发现自己离下一个路灯有 7 米的距离(最坏情况)。
为了让计算简单,你可以先假装自己向前走 7 米,然后看自己走到了第几个路灯处,那个数字就是你要的区间数。
- 如果本来就在路灯下(余数0),走 7 米还在两个路灯之间,区间数不变。
- 如果本来离下一个路灯很近(比如 1 米),走 7 米会超过下一个路灯,区间数+1。
这里的“走 7 米”就是 “加 (align-1)”。
7. 最后,如果还是觉得复杂,可以这样做:
不要管什么公式,你就用最笨的方法:
- 用
鸡蛋数 ÷ 容量,得到“商”和“余数”。 - 如果余数 > 0,就把商 +1。
这个方法永远不会错。
而(鸡蛋数 + 容量 - 1) ÷ 容量只是把这个过程合并成了一个除法,因为它巧妙地把“判断余数”藏在了加法里面。
如果你还是不能理解为什么要加 (容量-1),那完全没关系——你可以永远只用“除一下,看余数,有余数就加1”的方法。
很多程序员也是这样做的,反而更清晰。公式只是一种简写,并不是必须理解的。
希望这次能帮到你。如果还有困惑,请告诉我,我会换一个更简单的比喻。
