使用BigInteger查找200位素数

时间:2019-04-23 11:25:13

标签: java math kotlin primes prime-factoring

一种绝对有效的方法是从0开始直到找到200位素数。为此,我编写了此方法:

var primeList = arrayListOf(BigInteger("2"))
fun findNextPrime(num : BigInteger): BigInteger {
    val n = num + BigInteger.ONE
    val sqrt = sqrt(num)
    for (bigInteger in primeList) {
        if(bigInteger > sqrt){
            return n
        }
        if(n % bigInteger == BigInteger.ZERO){
            return findNextPrime(num + BigInteger.ONE)
        }
    }
    return n;
}

我将找到的数字添加到primeList中,并仅检查小于squareRoot的数字,即使这是我可以编写的最快算法,但找到一百万个数字后又花费了很长时间,只有7位数字。可能会一直死到200位数字(即使我的笔记本电脑是第8代i7)。所以我接下来要用的是:

n = 2 * 3 * 5 *... + 1

n是素数,使用此方法求高位数非常快,但是并不能确保确切地达到200位数。我得到198和201位数。但是没有200的代码很简单,但我仍然发布:

var all = BigInteger.ONE
primeList.forEach {
   all *= it
}
all++
println(all.toString().length)

2 个答案:

答案 0 :(得分:3)

并非1 +前n个素数的乘积始终是素数。在证明存在无限多个素数的证明中,您可能会误判它的作用。 是真的,如果p_1, p_2, ..., p_n是第一个n素数,则

p_1 * p_2 * ... * p_n + 1

是质数或包含大于任何p_i质数的质数,但这与要合成的数字一致。有关更多信息,请参见primorials上的Wikipedia文章。

在尝试输入200位数字的情况下,前92个质数+1的乘积为199位,而前93个质数+1的乘积为201位。在这两种情况下,Miller-Rabin test都表明它们是复合的。我无法将199位数字分解为因子,但将201位数字分解为因子

509558935064289364432032169616857776489168568369134671296055828054188240764364761921821351373922822013621199759688858354748131233614846920025560717744496960296617420071391914813530238313960697008021211 = 11587 * 43976778723076669062918112506848863078378231498156094873224806080451216083918595142989673890905568483094951217717170825472351016968572272376418461874902646094469441621765074205016849772500275913353

使用如此数量的数字,获得质数的唯一有效方法是随机生成目标大小的候选数并对其进行素数测试(使用类似Miller-Rabin检验的方法)。根据素数定理,200位素数相对较多,因此在实践中您可以很快找到这样的素数。例如,我用Miller-Rabin编写的Python脚本在不到一秒钟的时间内吐出了以下200位素数:

49675218696612399034240799519655205503986657506787162015105425670413948962864456158664793804627084299081036134562339483478437262146378569515417671690110863951848724044479367633926630234074394356492223

编辑时:这是我用来查找200位素数的Python脚本。该代码用于我正在密码学课程中的一门课程,因此我编写它的目的是易于讨论,而不是简洁或有效:

import random

#The following function finds s and d in
#n-1 = 2^s*d with d odd
def findSD(n):
    s = 0
    d = n-1
    while d % 2 == 0:
        s = s + 1
        d = d//2
    return s,d

def checkBase(a,n):
    s,d = findSD(n)
    x = pow(a,d,n)
    if x == 1 or x == n-1:
        return "probable prime"
    else:
        for i in range(s-1):
            x = pow(x,2,n)
            if x == 1:
                return "composite"
            elif x == n-1:
                return "probable prime"
        #if you get to this stage, -1 not reached despite s-1
        #squarings -- so must be composite
        return "composite"

def MSR(n,k):
    #Implements the Miller-Selfridge-Rabin test for primality
    for i in range(k):
        a = random.randint(2,n-2)
        if checkBase(a,n) == "composite":
            return "composite"
    #if you get here n has survived k potential witnesses, so
    return "probable prime"

#The following function is slightly different from the one discussed in class:

def prime(n):
    smallPrimes = [2,3,5,7,11,13,17,19]

    for p in smallPrimes:
        if n == p:
            return True
        elif n % p == 0:
            return False

    if MSR(n,20) == "composite":
        return False
    else:
        return True

def findPrime(maxN):
    while True:
        m = random.randint(1,maxN//2)
        n = 2*m+1
        if prime(n):
            return n

例如,findPrime(10**200)通常会为您提供200位数的质数(尽管有可能获得199位数甚至更少)。

答案 1 :(得分:3)

BigInteger类中有一个称为:

的方法
isProbablePrime(int)

它使用了与我们的朋友here相同的算法: 但是它也可以使用另一种算法来检查结果。它非常简洁。