【问题标题】:Stackoverflow exception while testing Miller Rabin测试米勒拉宾时出现 Stackoverflow 异常
【发布时间】:2010-12-05 19:17:06
【问题描述】:

全部,

我已经实现了一个生成 2 个随机素数的代码,并且这 2 个数字的乘法应该通过 Miller Rabin 素数测试。但是,我的代码一直在循环,试图找到一个通过 Miller rabin 测试并最终导致 Stackoverflow 异常的数字。代码如下:

private void populateRandomPrimes()
{
    onePrimeValue = RandomPrime.getValue();

    do
    {
        secondPrimeValue= RandomPrime.getValue();
    }while(onePrimeValue == secondPrimeValue);

    BigInteger calcNum = new BigInteger(Integer.toString(onePrimeValue*secondPrimeValue));

    try
    {
        **if (calcNum.isProbablePrime(20))**
            populateMultiplicativeForPlayer();
        else
            populateRandomPrimes();
    }
    catch (Exception io)
    {
        io.printStackTrace();
    }
}

在上面的代码中:
1 > RandomPrime 类返回一个随机的素数
2 > onePrimeValue 和 secondPrimeValue 都应该不同
3 > 由于代码行:if (calcNum.isProbablePrime(20)) 永远不会返回 true,所以我最终会调用相同的代码,直到我得到 Stackoverflow 异常

谁能建议我如何解决这个问题?

【问题讨论】:

  • 也许尽量不要使用递归...而是把它放到一个大的while循环中。您甚至可以放置一个计数器并让它在一定数量的迭代后停止/失败。
  • 如果您确定 calcNum.isProbablePrime() 工作正常,您应该按照 Paul 的建议。
  • 好吧 isProbablePrime() 工作正常,但我从来没有从 2 个素数中得到一个素数 .. 我只得到复合素数

标签: java exception primes


【解决方案1】:

请在您的问题下方查看我的评论...

private void populateRandomPrimes()
{
    while (true){
      onePrimeValue = RandomPrime.getValue();

      do
      {
          secondPrimeValue= RandomPrime.getValue();
      }while(onePrimeValue == secondPrimeValue);

      BigInteger calcNum = new BigInteger(Integer.toString(onePrimeValue*secondPrimeValue));

      try
      {
          if (calcNum.isProbablePrime(20)){
              populateMultiplicativeForPlayer();
              return;
          }
      }
      catch (Exception io)
      {
          io.printStackTrace();
      }
    }
}

【讨论】:

    【解决方案2】:

    将 calcNum 计算移到 do-while 循环内并添加一个额外的条件:

    private void populateRandomPrimes()
    {
        onePrimeValue = RandomPrime.getValue();
        BigInteger calcNum = null;
        do {
            secondPrimeValue= RandomPrime.getValue();
            calcNum = new BigInteger(Integer.toString(onePrimeValue*secondPrimeValue));
        } while(onePrimeValue.equals(secondPrimeValue) && !(calcNum.isProbablePrime(20));
    
        //if you get here, calcNum isProbPrime, so no need to check again
        try {
            populateMultiplicativeForPlayer();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    

    您遇到了这个问题,因为您没有确定的递归基本情况。此外,除非您知道自己在做什么,否则不要在对象上使用==。您的 do-while 条件应该使用 .equals() 来比较 onePrimeValuesecondPimeValue

    这种方法最坏的情况是你的程序会卡在infinite loop,因为do-while循环的退出条件永远不会满足。为了解决这个问题,您可以在循环中添加第三个条件,以确保它在固定次数的迭代后终止。

    【讨论】:

    • secondPrimeValueonePrimeValue 的类型为 int。所以我不需要使用 .equals() 。而且我实际上只是遇到了更糟糕的情况:)
    【解决方案3】:
    private BigInteger generateAppropriateNumber() {
        BigInteger result;
        boolean isOk = false;
        while (isOk == false) {
            onePrimeValue = RandomPrime.getValue();
            do {
                secondPrimeValue= RandomPrime.getValue();
            } while(onePrimeValue.equals(secondPrimeValue));
            BigInteger result = 
                  new BigInteger(Integer.toString(onePrimeValue * secondPrimeValue));
            if (result.isProbablePrime(20)) {
                isOk = true;
            }            
        }
        return result;
    }
    
    private void populateRandomPrimes() {
        populateMultiplicativeForPlayer(generateAppropriateNumber());
    }
    

    1. 使用循环而不是递归来避免堆栈增加。
    2. 不要使用全局变量。风格真的很差。

    【讨论】:

      猜你喜欢
      • 2014-07-28
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      • 2018-11-05
      • 2017-04-24
      相关资源
      最近更新 更多