死循环
- 死循环就是一个无法结束的循环。(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,确实是一个负数。 } }