真实面经题目 · 原创解析
如何实现 str2num,将字符串转换为整数或浮点数?
str2num 的重点是把符号、前导零、整数部分、小数部分、非法字符和溢出规则定义清楚,再用状态机或分段扫描实现。
真实面经题目 · 原创解析
str2num 的重点是把符号、前导零、整数部分、小数部分、非法字符和溢出规则定义清楚,再用状态机或分段扫描实现。
实现 str2num 不能只调用 parseInt。先跳过可选空白,处理正负号,再扫描整数部分;如果支持浮点数,遇到小数点后继续扫描小数部分,用 base 逐位缩小贡献。要定义非法输入、多个符号、多个小数点、空字符串、前导零、溢出和精度损失怎么处理。整数可在累乘 10 前做边界判断,浮点可分为 sign、integer、fraction 三段计算。面试中最好把它讲成有限状态机:start、sign、integer、dot、fraction、end、invalid。
允许哪些输入要先说清楚,例如空白、正负号、前导零、小数点、是否支持科学计数法、遇到非法字符是报错还是截断。
符号处理后逐字符读取数字,value = value * 10 + digit。每次累乘前检查是否超过目标整数范围,避免溢出后才发现。
支持浮点数时,小数点后每个 digit 按 0.1、0.01 等权重累加,或分别记录 fractional 和 scale,最后统一除以 scale。
用状态机处理 start、sign、integer、dot、fraction、end、invalid,可以系统约束字符顺序,避免多个符号或多个小数点被误接受。
工程实现要明确错误返回值、异常、NaN、clamp 到边界还是返回解析失败。面试题通常更看重边界定义和代码可维护性。
function str2num(input) {
const s = input.trim();
if (!s) throw new Error('empty input');
let i = 0;
let sign = 1;
if (s[i] === '+' || s[i] === '-') {
sign = s[i] === '-' ? -1 : 1;
i += 1;
}
let integer = 0;
let digits = 0;
while (i < s.length && s[i] >= '0' && s[i] <= '9') {
integer = integer * 10 + (s.charCodeAt(i) - 48);
i += 1;
digits += 1;
}
let fraction = 0;
let scale = 1;
if (s[i] === '.') {
i += 1;
while (i < s.length && s[i] >= '0' && s[i] <= '9') {
fraction = fraction * 10 + (s.charCodeAt(i) - 48);
scale *= 10;
i += 1;
digits += 1;
}
}
if (digits === 0 || i !== s.length) throw new Error('invalid number');
return sign * (integer + fraction / scale);
} 在 fraction 后增加 exponent 状态,处理 e/E、指数符号和指数数字,最后按 10 的指数调整结果。
在 value > (MAX - digit) / 10 时提前判定溢出,再按约定报错或截断到边界。
手写题考察边界、状态和数值表示,直接调用库函数无法展示这些设计。