标签:text == ESS 范围 产生 string alt 结果 补码
死循环
以上一篇随笔中的习题(找到 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++; } } }
一个特殊的例子
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 语句结束循环
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,确实是一个负数。 } }
标签:text == ESS 范围 产生 string alt 结果 补码
原文地址:https://www.cnblogs.com/buildnewhomeland/p/12158384.html