死循环(endless loop)

死循环

  • 死循环就是一个无法结束的循环。(endless loop / infinite loop)
  • 出现死循环是因为没有设置好结束条件,循环的结束条件很重要,要充分考虑各种边界情况

以上一篇随笔中的习题(找到 n 个可以被整除的数)为例,如果缺少累计次数的条件,那么就会让条件表达式永远满足,这样程序就会永远执行。这样就会产生一个死循环。

public class FindDivEndless {
    public static void main(String[] args) {
        int n = 5;
        int dividend = 100;
        int divisor = 89;

        int found = 0;

        while(found<n) {
            if(dividend%divisor == 0) {
                System.out.println(dividend + "可以被" + divisor + "整除。商为" + (dividend/divisor));
            }
            dividend++;
        }
    }
}

 

一个特殊的例子

  • 用 while 找出 5 个能被 20 0000 0000 整除的数
  • 程序最终依然会结束
public class FindNDivNotEndless {
    public static void main(String[] args) {
        int n = 5;

        int dividend = 100;
        int divisor = 2000000000; // 数值会溢出int的取值范围

        int found = 0;

        while (found < n) {

            if (dividend % divisor == 0) {
                found++;
                System.out.println(dividend + "可以被" + divisor + "整除。商为" + (dividend / divisor));
            }

            dividend++;
        }
    }
}

 

 出现这种情况的原因是,20亿接近 int 的最大取值,再往下累加就会导致数值溢出。

按照二进制的加法,那么加着加着,最高位就会是1,而在计算机中,二进制数值是用补码的形式表示和存储的,

因此最高位符号位是1时,就变成了负数,这就是为什么第二个找到的数是负数的原因。

于是,如果不仅仅找5个可以被整除的数时,就会不断的1、 -1、 0、 1、 -1 这样重复下去。

那么又如何解决数值溢出而产生负数结果的问题呢?

 

使用 break 语句结束循环

  • break语句可以结束任何循环
  • 不考虑负数的情况,使用 break 解决问题
public class FindNDivBetter {
    public static void main(String[] args) {
        int n = 5;

        int dividend = 100;
        int divisor = 2000000000;

        int found = 0;

        String start = "从" + dividend + "开始,";

        while (found < n) {
            // 当被除数数值溢出时,跳出整个while循环。
            if (dividend < 0) {
                System.out.println("被除数溢出,计算结束!");
                break;
            }

            if (dividend % divisor == 0) {
                found++;
                System.out.println(dividend + "可以被" + divisor + "整除。商为" + (dividend / divisor));
            }

            dividend++;
        }

        System.out.println(start + "共找到" + found + "个可以被" + divisor + "整除的数。");
        System.out.println(dividend); // 结果是-2147483648,确实是一个负数。
    }
}

posted @ 2020-01-06 20:35  见嘉于世  阅读(2647)  评论(0编辑  收藏  举报