如何修复因变量修改导致的无限循环问题

本文解析 java 中因在嵌套循环中错误修改外层循环变量(如 `i`)而引发的无限循环问题,并提供安全、高效的替代方案。

你的代码看似逻辑清晰:目标是计算所有 n 位数的乘积(即每个 n 位数各位数字相乘)之和。但程序卡死,根本原因在于——你在 while 循环中直接修改了外层 for 循环的控制变量 i

来看关键片段:

for (double i = start; i < finish; i++) {
    while (i > 0) {
        Digit = i % 10;
        MultipliedDigit *= Digit;
        i = i / 10; // ⚠️ 危险!这会破坏 for 循环的步进逻辑
    }
    Summary += MultipliedDigit;
}

这里 i 是 double 类型,且在 while 中不断执行 i = i / 10(例如 i=999 → 99.9 → 9.99 → 0.999…),它永远不会真正变为 ≤ 0(浮点精度下可能趋近于 0 但不等于 0),同时 for 循环的 i++ 也因 i 被覆盖而失效——最终导致外层循环永远无法终止。

✅ 正确做法:使用独立的临时变量处理数字拆分,绝不改动循环变量。

同时,应改用整数类型(long 或 int)避免浮点误差与性能损耗。

以下是修正后的完整代码:

import java.util.Scanner;

public class SummarynDigitNumbersDigitMultiplyDigit {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int n = s.nextInt();

        // 边界校验:n 至少为 1
        if (n < 1) {
            System.out.println(0);
            return;
        }

        long start = (long) Math.pow(10, n - 1);  // 最小 n 位数,如 n=2 → 10
        long finish = (long) Math.pow(10, n);     // 最小 (n+1) 位数,如 n=2 → 100

        long summary = 0;

        for (long num = start; num < finish; num++) {
            long temp = num;      // ✅ 用 temp 代替 num 进行各位提取
            long multipliedDigit = 1;

            // 特殊处理:若 num 含 0,则整个乘积为 0,可提前退出
            boolean hasZero = false;
            while (temp > 0) {
                int digit = (int) (temp % 10);
                if (digit == 0) {
                    hasZero = true;
                    break;
                }
                multipliedDigit *= digit;
                temp /= 10;
            }

            if (!hasZero) {
                summary += multipliedDigit;
            }
            // 若含 0,multipliedDigit 不参与累加(保持为 0,无需显式操作)
        }

        System.out.println(summary);
    }
}

? 关键改进说明:

  • 使用 long num 作为循环变量,long temp 作为副本处理各位数字;
  • 所有算术运算基于整数,规避 double 的精度丢失与除法截断问题(如 999/10=99.9 在 double 中不精确,而 999L/10=99L 精确);
  • 增加 hasZero 判断:一旦某位为 0,乘积即为 0,可跳过后续计算,提升效率;
  • 补充输入校验,防止 n ≤ 0 导致边界异常。

? 小结:在多层循环中,永远不要在内层修改外层循环变量;如需数值变换,请始终使用局部临时变量。这是避免隐蔽无限循环的黄金准则。