如何获得 N 位随机 "industrial grade" 素数,其中 5 < N < 20?

How do I get a N digit random "industrial grade" prime number where 5 < N < 20?

这段代码哪里做错了?生成 N 位随机数的更好方法是什么?

public static boolean isPrime(long n) {
if (n <= 3) {
    return n > 1;
} else if (n % 2 == 0 || n % 3 == 0) {
    return false;
} else {
    for (int i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}

}

public static long getPrime(int digit){
    long sample;
    long multiple = Math.round(Math.pow(10, digit));
    do{         
        sample = Math.round(Math.random()* multiple);
        //System.out.println(sample);
    }while(!isPrime(sample));
    return sample;
}

What am doing wrong here in this piece of code:

很多东西。

  1. 正如评论者指出的那样,您的素数测试在数学上是伪造的。

  2. 您实施的测试不正确。 Math.pow(...) 函数 returns 和 double,因此您可能会遭受精度损失。但是你需要完全精确的余数运算(%)才能给你正确的答案。

  3. 您忽略了标准 BigInteger class 提供的完美可用的素数生成和素数测试方法;有关详细信息,请参阅 javadoc

我的猜测是第 2 点是你所缺少的。

您的 getPrime() 方法几乎适用于 5 < N < 19。它不适用于 N = 19,因为最大可能的 long 值是 9223372036854775807,长度为 19 位。它对小于 19 的值不太有效的原因是它可以生成少于所需位数的数字。你需要 while(sample < (long) Math.pow(10, digit - 1) || !isPrime(sample))

现在您已经更新了您的 isPrime() 方法,它几乎可以工作,但您需要更换

for (int i = 5; i * i <= n; i += 6) 

来自

for (long i = 5; i * i <= n; i += 6) 

否则 i * i 的值可能会溢出。

Math.random() 只有 15-16 位精度,因此不会生成所有 16、17、18、19 或 20 位数字。问题是第 16、17、18、19、20 位数字更有可能分别是 2、4、8、16 和 32 的倍数,因此不是质数。

我建议你使用SecureRandom.nextLong()取低N位。