Java無限迴圈問題

yoyochina發表於2009-02-16

        首先需要說明的是,以下問題都是出自《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
    } 
}

  

 

 

相關文章