2017-08-29 163 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

是的,我改变了一下我的评论。从来没有使用过浮动很多,有趣的是你遇到问题的速度有多快。 –