2017-08-29 80 views
1

我有一個程序(代碼如下),模擬一個骰子滾動指定數量的卷(num;),然後打印結果。 出於某種原因,程序可以完成的最大滾動數量是2,147,483,583,而不是2,147,483,647的整數限制。當輸入2,147,483,647作爲卷的數量時,程序根本不會產生輸出。爲什麼試圖通過for循環導致無限循環而達到2,147,483,647?

這是否有特定的原因?

import java.security.SecureRandom; 

public class RollDie { 
// number of rolls 
private static float num = 2147483583; 

public static void main(String[] args) throws InterruptedException { 
    long start = System.currentTimeMillis(); 
    System.out.print("Rolling...\n"); 

    SecureRandom randomNumbers = new SecureRandom(); 
    int frequency1 = 0; 
    int frequency2 = 0; 
    int frequency3 = 0; 
    int frequency4 = 0; 
    int frequency5 = 0; 
    int frequency6 = 0; 

    for (int roll = 1; roll <= num; roll++) { 
     // randomly selecting face ('rolling') 
     int face = 1 + randomNumbers.nextInt(6); 

     switch (face) { 
     case 1: 
      ++frequency1; 
      break; 
     case 2: 
      ++frequency2; 
      break; 
     case 3: 
      ++frequency3; 
      break; 
     case 4: 
      ++frequency4; 
      break; 
     case 5: 
      ++frequency5; 
      break; 
     case 6: 
      ++frequency6; 
      break; 
     } 
    } 

    long end = System.currentTimeMillis(); 
    long totalTime = ((end - start)/1000); 
    // displaying results 
    System.out.println("\nFace\tFrequency"); 
    System.out.printf("1\t%d%n2\t%d%n3\t%d%n4\t%d%n5\t%d%n6\t%d%n", 
      frequency1, frequency2, frequency3, frequency4, frequency5, 
      frequency6); 
    System.out.println("\nTime taken: " + totalTime + " seconds."); 
    } 
} 
+0

如果你調試了一下以找出這裏發生了什麼,並詢問了一個更具體的問題(或兩個),這個問題將具有更多的未來價值。 – Dukeling

+0

有關如何編輯我的帖子以改善它的任何建議? @Dukeling –

+0

問題是,要達到這個問題的理想版本將需要對您的問題進行根本改變,但在此階段這樣做會使部分答案無效,這並不好。更具體地說,這裏有兩個問題 - (1)試圖用'float'表示大整數,(2)試圖循環到2,147,483,647 - 理想情況下應該是兩個單獨的問題,但兩個答案都解決這兩個問題,所以你現在無法真正縮小它的範圍。但是,您可以做的是[儘可能減少代碼](https://ideone.com/CVZ0Gr)。 – Dukeling

回答

3

沒有輸出,因爲for循環永遠不會終止。您必須將條件從for (int roll = 1; roll <= num; roll++)更改爲for (int roll = 0; roll < num; roll++)

在您的情況下,滾動達到Integer.MAX_VALUE,條件爲仍然爲真,因此循環再次進入。現在滾動增加,溢出到Integer.MIN_VALUE,並且是仍然< = num。因此,for循環從不停止。

此外,您將遇到numfloat的問題,請參閱Eran's answer以獲得解釋。

2

您的num變量爲float類型。 float類型的精度有限,因此它不能準確地表示任何大的int值。

第二個問題是由Malte指出的 - 當您將限制設置爲Integer.MAX_VALUE時,由於int溢出,您的循環不會終止。

如果將num更改爲int並將環路條件更改爲roll < num,則循環將在正確的迭代次數後終止。

+0

更改'num'的類型並不能完全解決問題。這不起作用的原因是for循環的結束條件。它永遠不會中斷,因爲'roll'溢出。不過,我同意,浮點數可能需要不正確的循環執行次數。 –

+0

@MalteHartwig你部分正確,我部分正確。完整答案是兩個答案的組合。您的解決方案將防止無限循環,但循環會過早退出(當roll == 2147483584)時。 – Eran

+0

是的,我改變了一下我的評論。從來沒有使用過浮動很多,有趣的是你遇到問題的速度有多快。 –