深蓝黑背景封面。左侧是费米估算因子链示意,顶部一行小字「示例:一颗 CPU 每秒大约执行多少条指令?」;其下三个并排因子方框用乘号连接:「主频 ~10⁹ Hz(每秒周期数)」×「IPC ~10⁰(每周期指令数)」×「核数 ~10¹(并行核心数)」;一个向下箭头指向青色高亮结论框「≈ 10¹⁰ 条指令/秒」,结论框副注「数量级正确即可,误差在一个数量级以内」。底部三行小注「每个因子都敢猜:按 1、3、10 档位取整」「高估与低估互相抵消,乘积往往不离谱」「面试要的不是精确值,是拆解过程」。右侧大标题两行「面试里的数量级估算」「费米估算法怎么拆」,副标题「把算不出的大问题,拆成一串敢猜的小因子」,小注「界定问题 → 拆因子 → 取数量级 → 交叉验证」。左上角标注「知识延伸 · 估算方法」,右上角圆角胶囊标注「Day 01 · 11-28」。 图 1:本文封面,一条典型的费米因子链。

面试里有一类让人当场卡壳的题:「一颗 CPU 每秒大约执行多少条指令」「一座城市有多少部电梯」。这个系列另有一篇真题解析专门拆解 CPU 指令那道题的硬件背景,本篇换个视角:把这类题背后的通用方法论——费米估算法——讲透。学会这套拆解套路,任何「算不出」的问题都能拆成一串「敢猜」的小因子。先说明,本文示例中的公开量级数据只做定性量级判断,不追求精确数字。

费米估算的四步套路。

第一步,界定问题。先别急着算,问清口径:估什么对象、什么单位、什么范围。「一座城市有多少部电梯」——是行政区还是建成区?只算载人电梯还是含货梯?口径不同结果差几个数量级,主动澄清口径本身就是加分项。第二步,拆因子。把目标量写成一条乘法链,让每个因子都落在常识可及的范围内。第三步,取数量级。每个因子按 1、3、10 的档位取整——一个因子你觉得在 2 到 5 之间,取 3;在 10 到 30 之间,取 10。取整到档位之后,整条链心算就能完成。第四步,交叉验证。换一条不同的拆法再算一遍,两个结果量级一致就可以交卷;差出一个数量级以上,回头检查哪个因子的估计最可疑。

拆因子为什么有效:误差被关进了笼子。

直接拍一个大总量,误差是没有约束的——让你直接猜「全国一年喝掉多少杯咖啡」,差出百倍都不奇怪。但拆成「人口 × 喝咖啡的人口比例 × 每人每年杯数」之后,每个因子都是生活常识范围内的小量,单因子估值很少偏离真实值几倍以上;而且乘法链里有的因子偏高、有的偏低,高估与低估在乘积中会部分抵消。用一段蒙特卡洛模拟把这句话量化(Node.js 22.15.0,node fermi.js):真实总量设为 10⁹,一种方式是直接估总量、误差按 ±100 倍随机,另一种拆成 5 个因子、每个因子误差按 ±3 倍随机,各跑 20 万次:

const N = 200000, trueTotal = 1e9;
function direct() {
  return trueTotal * 100 ** (Math.random() * 2 - 1);   // 总量误差 ±100 倍
}
function chain(nFactors) {
  const trueFactor = trueTotal ** (1 / nFactors);
  let est = 1;
  for (let k = 0; k < nFactors; k++) {
    est *= trueFactor * 3 ** (Math.random() * 2 - 1);  // 每因子误差 ±3 倍
  }
  return est;
}
function report(name, fn) {
  let sum = 0, over10 = 0;
  for (let i = 0; i < N; i++) {
    const d = Math.abs(Math.log10(fn() / trueTotal));
    sum += d;
    if (d > 1) over10++;
  }
  console.log(`${name}: 平均偏差 ${(sum / N).toFixed(2)} 个数量级, 偏差超过10倍的比例 ${(100 * over10 / N).toFixed(1)}%`);
}
report('直接估总量(±100倍)', direct);
report('拆5个因子(各±3倍)', () => chain(5));

实测输出:

直接估总量(±100倍): 平均偏差 1.00 个数量级, 偏差超过10倍的比例 50.1%
拆5个因子(各±3倍): 平均偏差 0.50 个数量级, 偏差超过10倍的比例 10.6%

拆因子后平均偏差减半,偏差超过 10 倍的比例从约 50% 降到约 11%。这就是方法论的数学底气:它不是让你猜得更准,而是让误差的上限可控。

一道完整的示例:一座城市有多少部电梯。

界定口径:一座千万人口量级的特大城市,只算运行中的载人电梯。拆因子:人口取 10⁷ 量级;人均电梯占有率——住宅、写字楼、商场、医院加起来,粗略按每百人一部取 10⁻²。乘起来约 10⁵ 部。交叉验证:换一条拆法,按楼宇算——全市高层楼宇按 10⁴ 栋量级估,每栋平均电梯数按 10¹ 量级估,同样落在 10⁵ 量级。两条路径指向同一个数量级,答案就可信了。再次强调,这里的人口、楼宇数都是定性量级,面试要的不是精确值,是这条可辩护的拆解过程。

深蓝黑背景概念图。顶部小字「概念图 · 费米估算方法」,主标题「四步把『没法算』拆成『可以猜』」。上部是四张横向步骤卡,箭头相连:① 界定问题——先问清口径:估什么对象、什么单位、什么范围;② 拆因子——写成乘法链,让每个因子落在常识范围;③ 取数量级——每个因子按 1、3、10 档取整,心算可完成;④ 交叉验证——换一条拆法再算,量级一致就可信。中部左侧卡片「示例因子链:一座城市的电梯数量」,画出 人口 ~10⁷ 人 × 电梯占有率 ~10⁻² 部/人 → ≈ 10⁵ 部 的乘法链,副注「只做定性量级判断,不追求精确数字」。中部右侧卡片「为什么拆因子有效」列三条:误差相消——单因子的高估与低估在乘积中部分抵消;每步可辩护——面试官能逐因子追问与修正;目标是 10 的几次方,不是小数点后几位。底部总结条写「费米估算 = 乘法拆解 + 数量级取整 + 双路互验:差几倍可以接受,不拆就没法谈」。 图 2:四步套路、电梯示例与误差相消原理。

面试现场的答题姿态。

遇到估算题最忌讳两种反应:直接报一个数,或者说「这没法算」。正确的姿态是把思考过程外化:先复述并澄清口径,再写下因子链,每个因子报出自己的档位取整和理由——「这个因子我取 10,理由是……」,让面试官能逐因子追问和修正。算完主动做交叉验证,最后坦白误差边界:「真实值大概率在 10⁴ 到 10⁶ 之间,我更倾向 10⁵」。这套流程展示的是结构化思考能力,恰恰是估算题真正要考察的东西。日常工程里它同样好用:容量规划估 QPS、给服务定内存预算、评估一次迁移的数据量,都是同一条因子链思维。你被问过最刁钻的估算题是什么?当时拆成了哪几个因子?欢迎分享。