咨询:JavaScript完全数判定程序相邻值被跳过/未定义问题
我来帮你排查一下这个JavaScript程序里的问题,你遇到的相邻值被跳过、出现未定义的情况,主要是输入处理的逻辑出了问题,咱们一步步理清楚:
问题分析
1. 重复调用readline()导致输入被跳过
在你的sumDivisors函数里,这个while循环的写法有明显问题:
while(readline()){ sumDivisors(readline()); }
每次循环时,readline()会被调用两次:第一次是用来判断循环条件(这时候已经读取了一个输入值),第二次是作为参数传给sumDivisors(又读取了下一个输入值)。这就直接跳过了第一次读取到的值,导致每隔一个输入就被丢弃,正好对应你说的“相邻值被跳过”的情况。
2. 函数职责耦合,引发未定义问题
你把输入循环的逻辑塞进了计算因数和的函数里,这会让函数的职责变得混乱。而且当readline()返回null(没有更多输入)时,你还是会把它传给sumDivisors,此时num会变成undefined,在执行i < num的循环时就会触发错误,出现未定义相关的问题。
3. 最后一行代码不完整
你最后写的pri...明显是遗漏了调用sumDivisors(num)的代码,否则第一个输入值根本不会被处理。
修复后的完整代码
我们把输入处理和因数计算的逻辑分开,确保每个输入都被正确读取和处理:
// 专门处理输入读取的函数 function processAllInputs() { let input; // 循环读取所有输入,每次只调用一次readline() while ((input = readline()) !== null) { // 把输入转为数字类型,避免字符串导致的循环错误 sumDivisors(parseInt(input)); } } // 专注计算因数和并判断数的类型的函数 function sumDivisors(num) { // 处理小于2的特殊情况,比如1的真因数和是0 if (num < 2) { console.log(`${num} not perfect`); return; } let sum = 0; // 优化因数遍历:只遍历到num的平方根,大幅减少循环次数 for (let i = 1; i <= Math.sqrt(num); i++) { if (num % i === 0) { sum += i; // 处理成对的因数,同时避免把num本身加进去 const pairedDivisor = num / i; if (pairedDivisor !== i && pairedDivisor !== num) { sum += pairedDivisor; } } } // 判断并输出结果 if (sum === num) { console.log(`${num} perfect`); } else if (Math.abs(sum - num) === 2) { console.log(`${num} almost perfect`); } else { console.log(`${num} not perfect`); } } // 启动程序 processAllInputs();
关键优化说明
- 输入逻辑解耦:把读取输入的逻辑单独抽出来,每次循环只调用一次
readline()并存储值,彻底解决输入被跳过的问题。 - 类型安全处理:用
parseInt()把输入转为数字,避免输入是字符串时导致的循环异常。 - 因数计算优化:遍历到
Math.sqrt(num),同时处理成对的因数,比原来遍历到num-1的效率高很多,尤其是处理大数的时候。 - 特殊情况兜底:增加了对小于2的数字的判断,避免出现不必要的错误。
- 简化判断逻辑:用
Math.abs(sum - num) === 2代替原来的两个条件,代码更简洁易读。
这样修改后,程序就能正确处理每一个输入值,不会再出现跳过或者未定义的问题了。
内容的提问来源于stack exchange,提问作者wangonya
相关产品推荐
相关产品推荐

