`

Java无限循环问题

    博客分类:
  • Java
阅读更多

        首先需要说明的是,以下问题都是出自《Java解惑》,这里做一个整理,也加深一下印象。

 

       下面所有的问题都是给出一个循环,给它加一个什么样的变量声明,使它作用于循环上时能够使循环无限循环下去(即变成一个无限循环)。

 

1.

for (int i = start; i <= start + 1; i++) {} 

     

      这个问题还比较简单,只需要这样声明即可(注意:上面的是小于等于号):int start = Integer.MAX_VALUE - 1;

 

2.

While (i == i + 1) {} 

     

         如果 i 在循环开始之前被初始化为无穷大,无穷大加 1 还是无穷大,那么终止条件测试(i == i + 1)就会被计算为 true,从而使循环永远都不会终止。这样声明即可:double i = Double.POSITIVE_INFINITY;

      事实上,任何足够大的浮点数都可以实现这一目的,例如:  double i = 1.0e40; 这样做之所以可以起作用,是因为一个浮点数值越大,它和其后继数值之间的间隔就越大。浮点数的这种分布是用固定数量的有效位来表示它们的必然结果。对一个足够大的浮点数加 1 不会改变它的值,因为 1 是不足以“填补它与其后继者之间的空隙”。 

 

3.

while (i != i) { } 

       

         IEEE 754 浮点算术保留了一个特殊的值用来表示一个不是数字的数量,这个值就是 NaN(“不是一个数字(Not a Number)”的缩写),对于所有没有良好的数字定义的浮点计算,例如 0.0/0.0,其值都是它。规范中描述道,NaN 不等于任何浮点数值,包括它自身在内。因此,如果 i 在循环开始之前被初始化为 NaN,那么终止条件测试(i != i)的计算结果就是 true,循环就永远不会终止。很奇怪但却是事实。  可以这样声明:double i = 0.0 / 0.0;
     为了表达清晰,可以使用标准类库提供的常量: double i = Double.NaN;

 

4.

while (i != i + 0) { } 

      

         注意:此题不使用浮点数。

      我们必然可以得出这样的结论,即 i 的类型必须是非数值类型的,并且这其中存在着解谜方案。唯一的 + 操作符有定义的非数值类型就是 String。+ 操作符被重载了:对于 String 类型,它执行的不是加法而是字符串连接。如果在连接中
的某个操作数具有非 String 的类型,那么这个操作书就会在连接之前转换成字符串。 

      事实上,i 可以被初始化为任何值,只要它是 String 类型的即可,例如:String i = "Hello";

 

5.

while (i <= j && j <= i && i != j) { } 

     

        在Java5.0版本及以后,<=操作符在原始数字类型集上是反对称的,但是<=操作符在被包装的数字类型(Byte、Character、Short、Integer、Long、Float 和 Double)的操作数上不是反对称的,因为 Java 的判等操作符(==和!=)在作用于对象引用时,执行的是引用ID 的比较,而不是值的比较。

     所以这样声明即可:  Integer i = new Integer(0);  Integer j = new Integer(0); 

public class Test4 
{
	public static void main(String[] args) 
	{ 
		System.out.println(new Integer(0) == 0); //输出:true
		System.out.println(new Integer(0) == new Integer(0)); //输出:false
    } 
}

 

 6.

while (i != 0 && i == -i) { } 

     

        可以推断出 i 的类型必然是整数型的。总共存在偶数个 int 数值——准确地说有2的32次方个——其中一个用来表示 0,这样就剩些奇数个 int 数值来表示正整数和负整数,这意味着正的和负的 int 数值的数量必然不相等。这暗示着至少有一个 int数值,其负值不能正确地表示成为一个 int 数值。 

     事实上,恰恰就有一个这样的 int 数值,它就是 Integer.MIN_VALUE,十六进制表示是 0x80000000。其符号位为 1,其余所有的位都是 0。如果我们对这个值取负值,那么我们将得到 0x7fffffff+1,也就是 0x80000000,即
Integer.MIN_VALUE!因此,Integer.MIN_VALUE 是它自己的负值,Long.MIN_VALUE 也是一样。对这两个值取负值将会产生溢出,但是 Java 在整数计算中忽略了溢出。

     因此可以这样声明:int i = Integer.MIN_VALUE; 或者:long i = Long.MIN_VALUE;

public class Test4 
{
	public static void main(String[] args) 
	{ 
		int i = Integer.MIN_VALUE;
		long j = Long.MIN_VALUE;
		
		System.out.println(i == -i); //输出:true
		System.out.println(j == -j); //输出:true
    } 
}

  

 

 

2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics