生成具有指定最后数字的大质数

时间:2010-12-04 17:32:07

标签: c# java algorithm primes

想知道如何生成512位(155位十进制数)素数,其中最后五位十进制数被指定/固定(例如。*** 28071)??

在没有任何规范的情况下生成简单素数的原则是可以理解的,但我的情况更进一步。

至少,我应该从哪里开始提示?

最好使用Java或C#。

谢谢!

8 个答案:

答案 0 :(得分:7)

我想唯一的方法就是首先生成一个150个十进制数字的随机数,然后通过number = randomnumber * 100000 + 28071将其后面的28071附加到其后面,然后用类似

的方法强行推出它
while (!IsPrime(number))
    number += 100000;

当然这可能需要一段时间来计算; - )

答案 1 :(得分:7)

您是否尝试过生成此类数字并进行检查?我希望这个速度可以接受。素数密度仅作为数字的对数减小,所以我希望你尝试几百个数字,直到你达到一个素数。 ln(2^512) = 354所以350左右的一个数字将是素数。

  

粗略地说,素数定理表明如果选择一个大数N附近的随机数,则它的素数大概是1 / ln(N),其中ln(N)表示N的自然对数。例如,在N = 10,000附近,大约九分之一的数字是素数,而在N = 1,000,000,000附近,每21个数字中只有一个是素数。换句话说,N附近的素数之间的平均差距大致为ln(N)

(来自http://en.wikipedia.org/wiki/Prime_number_theorem

您只需要注意最终数字的编号。但我认为这就像检查最后一个数字不能被2或5整除一样容易(即它是1,3,7或9)。

根据this performance data,您可以对每秒512位数据执行大约2000次ModPow操作,并且由于简单的质数测试是检查2^(p-1) mod p=1这是一个ModPow操作,您应该能够生成几个具有每秒属性的素数。

所以你可以做(​​伪代码):

BigInteger FindPrimeCandidate(int lastDigits)
{
    BigInteger i=Random512BitInt;
    int remainder = i % 100000;
    int increment = lastDigits-remainder;
    i += increment;
    BigInteger test = BigInteger.ModPow(2, i - 1, i);
    if(test == 1)
      return i;
    else
      return null;
}

对该函数的结果进行更广泛的质检。

答案 2 :(得分:3)

正如@Doggot所说,但从最少可能的150位数字开始,以28071结尾,意味着100000 ...... 0028071,现在每次加100000并测试主要使用米勒rabin,就像我提供的代码一样{ {3}},它需要一些自定义。如果返回值为true,请首先检查它是否正确。

答案 3 :(得分:2)

您可以使用仅包含满足您特殊条件的数字的筛子来筛选出可被小素数整除的数字。

对于每个小素数p,您需要找到正确的起点和步骤,考虑到筛子中只有每个第100000个数字。

对于在筛子中存活的数字,您可以使用BigInteger.isProbablePrime()以足够的概率检查它是否为素数。

答案 4 :(得分:2)

让ABCDE成为您考虑的基数为十位的五位数。基于Dirichlet's theorem on arithmetic progressions,如果ABCDE和100000是互质的,那么形式为100000 * k + ABCDE的无限多个素数。既然您正在寻找素数,那么无论是2还是5都不会划分ABCDE,因此ABCDE和100000是互质的。所以你正在考虑的形式有很多无限的素数。

答案 5 :(得分:1)

您可以通过添加额外约束来扩展standard methods for generating large primes中的一个,即最后5个十进制数字必须正确。天真地,你可以把它作为一个额外的测试添加,但它会增加找到合适的素数的时间10 ^ 5.

不那么天真地:生成随机的512位数,然后设置足够的低位,以便十进制表示以所需的顺序结束。然后继续正常的素性测试。

答案 6 :(得分:1)

让我们考虑蛮力。看看这个非常有趣的文章“素数彩票”:

鉴于最后一个表中的最后一个条目,有大约2.79 * 10 ^ 14个素数小于10 ^ 16。因此,大约每35个数字是该范围内的素数。

编辑:查看CodeInChaos的评论 - 如果你只走几千个512位数字并修复了最后5位数字,你会很快找到一个。

答案 7 :(得分:1)

http://www.merriampark.com/bigsqrt.htmint类的帮助下,我将蛮力算法从BigDecimal世界改写为BigSquareRoot。 (注意,从1到1000,据说恰好是168个素数。)

很抱歉,但如果你把你的范围放在那里,即< 10 154 ; 10 155 -1&gt ;,你可以让你的电脑工作,当你退休时,你可能会得到结果......它太慢了!

但是,您可以通过某种方式找到至少其中一部分与此线程中的其他答案结合使用。


package edu.eli.test.primes;

import java.math.BigDecimal;

public class PrimeNumbersGenerator {

  public static void main(String[] args) {
//    BigDecimal lowerLimit = BigDecimal.valueOf(10).pow(154); /* 155 digits */
//    BigDecimal upperLimit = BigDecimal.valueOf(10).pow(155).subtract(BigDecimal.ONE);

    BigDecimal lowerLimit = BigDecimal.ONE;
    BigDecimal upperLimit = new BigDecimal("1000");

    BigDecimal prime = lowerLimit;
    int i = 1;

    /* http://www.merriampark.com/bigsqrt.htm */
    BigSquareRoot bsr = new BigSquareRoot();
    upperLimit = upperLimit.add(BigDecimal.ONE);
    while (prime.compareTo(upperLimit) == -1) {

      bsr.setScale(0);
      BigDecimal roundedSqrt = bsr.get(prime);

      boolean isPrimeNumber = false;
      BigDecimal upper = roundedSqrt;
      while (upper.compareTo(BigDecimal.ONE) == 1) {

        BigDecimal div = prime.remainder(upper);
        if ((prime.compareTo(upper) != 0) && (div.compareTo(BigDecimal.ZERO) == 0)) {
          isPrimeNumber = false;
          break;
        } else if (!isPrimeNumber) {
          isPrimeNumber = true;
        }

        upper = upper.subtract(BigDecimal.ONE);
      }

      if (isPrimeNumber) {
        System.out.println("\n" + i + " -> " + prime + " is a prime!");
        i++;
      } else {
        System.out.print(".");
      }
      prime = prime.add(BigDecimal.ONE);
    }
  }

}