测试Miller Rabin时出现Stackoverflow异常

时间:2010-12-05 19:17:07

标签: java exception primes

所有

我已经实现了一个生成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类返回随机 prime 数字
2> onePrimeValue和secondPrimeValue都应该不同
3>由于代码行:if (calcNum.isProbablePrime(20))永远不会返回true,因此我最终会调用相同内容,直到我获得Stackoverflow异常

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

3 个答案:

答案 0 :(得分: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();
      }
    }
}

答案 1 :(得分:1)

在do-while循环中移动calcNum计算并添加一个额外条件:

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();
    }
}

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

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

答案 2 :(得分:1)

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. 不要使用全局变量。这是非常糟糕的风格。