图 1:本文封面,点明题目与两条解题路线。
先说明属性:这是一篇经典题解析,题目出自本地历史面试资料,并非任何公司的当前招聘原题。这类「禁用数学库、手写开方」的题目在手写代码环节反复出现,值得吃透。
想象你在面试现场,白板上写着:已知 sqrt(2) 约等于 1.414,不用数学库,把它精确到小数点后 10 位。
第一步,审题。
题目给了三个关键信息:禁用数学库,意味着只能用最基础的四则运算;「精确到小数点后 10 位」,意味着误差要小于 1e-10,这是终止条件;「已知约等于 1.414」,暗示答案落在 1 和 2 之间,给你初始区间。能看出这三点,题就解了一半。
第二步,基础回答:二分逼近。
sqrt(2) 满足 x² = 2,而平方运算我们会写。于是问题变成:在区间 [1, 2] 里找一个数,使它的平方尽量接近 2。每次取中点 mid,mid² 大于 2 就把右边界收到 mid,否则把左边界推到 mid。每迭代一次,区间宽度减半。初始宽度为 1,要让宽度小于 1e-10,约需 34 次迭代——因为 2 的 34 次方约 1.7e10,刚好压过精度要求。
核心逻辑用代码写出来只有几行(以下为解释性片段,仅说明二分步骤,不是完整程序):
let lo = 1, hi = 2;
while (hi - lo > 1e-10) {
const mid = (lo + hi) / 2;
if (mid * mid > 2) hi = mid; else lo = mid;
}
// lo 与 hi 之间的任意值都满足精度要求
第三步,追问:还能更快吗?牛顿迭代。
把开方看成求 f(x) = x² - 2 = 0 的根,用切线逼近:x 更新为 (x + 2/x) 再除以 2。这个公式也叫巴比伦方法。它是平方收敛的——误差每一步大致平方一次,从初值 2 出发,四五步就能撞到 1e-10 以内。能主动从二分讲到牛顿,并说出收敛速度差异,通常就是这道题的加分点。
图 2:二分法与牛顿迭代逼近 sqrt(2) 的对比——前者每步缩半区间,后者平方收敛。
第四步,工程上怎么用。
这类迭代逼近不是纸上功夫:没有浮点开方指令的嵌入式环境、需要自定义精度的数值库、图形学里的快速逆平方根思路,都是同一族方法。对 AI 工程岗位来说,关联更直接——模型训练本质就是迭代逼近:每一轮更新参数、检查损失是否小于阈值,与这里「每一轮更新 x、检查误差」是同构的。收敛太快或太慢怎么调、什么时候该提前停止、精度目标定在哪才不浪费算力,这些训练日常问题在这道小题里都能找到雏形。理解收敛判据和精度控制,是理解训练循环的入门课。
回到面试现场,建议的答题节奏是:先复述题目确认精度要求,再给二分写出可运行逻辑,主动补牛顿迭代并对比收敛速度,最后用边界情况和易错点收尾。全程不超过十五分钟,但四层能力——建模、编码、分析、工程意识——都展示到了。
易错点清单。
一,终止条件写错:用 |x² - 2| 还是用区间宽度,量级不同,要和面试官确认或直接说明你的选择。二,精度和位数混淆:保留 10 位小数要求误差小于 1e-10,实现时阈值最好再收一位,避免四舍五入踩线。三,边界没处理:输入为 0、输入小于 1 时区间怎么取,能答出来才显得完整。四,浮点死循环:当 lo 和 hi 已经是相邻的浮点数,中点会等于端点之一,区间不再缩小,工程实现要加迭代次数上限兜底。五,牛顿法初值选得太差导致迭代变慢,虽然对本题都会收敛,但值得提一句。
到这里,白板上的答案、口头追问、工程延伸就都有了。这道题的价值不在于背下牛顿公式,而在于展示你把「无限逼近」翻译成「有限循环」的能力。
如果面试官把题目改成 sqrt(0.5) 或者 sqrt(1e20),你的二分初始区间和牛顿初值会怎么调整?欢迎写出你的改法。
参考资料
- Node.js v22.x 官方 API 文档(运行环境说明) — https://nodejs.org/docs/latest-v22.x/api/