JS字符串切片未达末尾?长数字奇数子串提取异常排查
问题分析与解决方案
嘿,这个问题我太熟悉了!核心原因是JavaScript Number类型的精度限制在捣蛋,咱们一步步把它说清楚:
为什么长字符串会失效?
你代码里用了slicing % 2 !== 0来判断子串是否为奇数,这时候JavaScript会自动把字符串slicing转换成Number类型。但Number是双精度浮点数,它能精确表示的最大整数是2^53 - 1(也就是9007199254740991)——大概是16位数字。
当你的子串长度超过这个范围时,转成Number后会丢失精度,变成一个近似值。这时候取余运算的结果就完全不准了:原本是奇数的长数字串,转成Number后可能被近似成偶数,导致代码错误地跳过了这些子串,看起来就像“切片到某位置就停了”。
比如你提到的"93711892377292643",这个数字已经远超出安全整数范围,转成Number后精度丢失,取余2的结果变成了0,所以不会被加入数组,自然就看不到后面的子串了。
怎么解决?
其实判断一个数是不是奇数,根本不需要把整个数转成数字——只看最后一位数字就行! 因为奇偶性完全由最后一位决定。这样既避开了大数精度问题,还能大幅提升代码效率。
修改后的代码如下:
function solve(s) { var newarray = []; // 外层循环:起始索引从0到字符串末尾前一位 for (var i = 0; i < s.length; i++) { // 内层循环:结束索引从起始索引+1开始,避免生成空串 for (var j = i + 1; j <= s.length; j++) { // 取子串的最后一位字符,转成数字判断奇偶 var lastDigit = parseInt(s[j - 1]); if (lastDigit % 2 !== 0) { newarray.push(s.slice(i, j)); } } } return newarray.length; }
额外优化点
- 去掉了原代码中
i <= s.length和j <= s.length的冗余循环:当i >= j时,slice(i,j)会得到空串,完全没必要处理这些情况; - 直接操作字符串的最后一位字符,避免了长字符串转数字的性能开销;
- 彻底解决了大数精度丢失的问题,不管字符串多长都能正确判断。
内容的提问来源于stack exchange,提问作者user9279766
相关产品推荐
相关产品推荐

