【问题标题】:find 200 digit prime numbers using BigInteger使用 BigInteger 查找 200 位素数
【发布时间】:2019-09-12 13:47:51
【问题描述】:

一种绝对有效的方法是从 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 位数。(即使我的笔记本电脑是 i7 第 8 代)。所以我使用的下一件事是:

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

嗯,n 是素数,使用这种方法获得高位数字非常快,但没有什么能确定准确地达到 200 位数字。我得到了 198 和 201 位数字。但没有 200 代码很简单,但我还是发布吧:

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

【问题讨论】:

  • btw all += all * it 不计算 primeList 的乘积
  • gist.github.com/domnikl/6ad30f0a6ca3228f44e8273c08dbd879你可以更改大整数的代码。
  • kotlin 中有序列的概念。你应该调查一下。另外第200个价格是1217,不是那么大,所以你可以用整数。
  • well n is prime ?一般来说,这不是真的。并非所有 primorials 与素数相差 1。要获得 200 位长的素数,唯一可行的方法是生成该大小的随机奇数并测试它们的素数。换句话说——为他们钓鱼
  • 我刚刚对跨越 200 位数的两个原始素数候选者进行了米勒-拉宾测试。两者都是合数。

标签: java math kotlin primes prime-factoring


【解决方案1】:

1 + 第一个n 素数的乘积并不总是素数。你可能记错了它在证明有无限多个素数中的作用。 如果p_1, p_2, ..., p_n是第一个n素数那么

p_1 * p_2 * ... * p_n + 1

要么是素数,要么包含大于任何p_i 的素数因子,但这与复合数一致。有关更多信息,请参阅primorials 上的维基百科文章。

在尝试 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 位或更小的数字)。

【讨论】:

  • 一位大学硕士告诉我,3*5*7... 总是有效的。看起来他有点不对劲。谢谢你让我知道。顺便说一句,甚至分享你的如果您不喜欢 kotlin 或 java,python 代码可以提供帮助 :) 所以请发布它,谢谢。
  • @stevemoretz 我添加了代码。 3*5*7 ... + 1 被用来证明存在任意大的素数,所以如果你只记得这个事实并且有一段时间没有完成证明,很容易看出数字本身不一定是素数的细则可能会丢失。
  • 对不起,你所说的可能的素数是什么意思?我们还不确定你的意思吗?
  • @stevemoretz Miller Rabin 检验是概率性的。它不能证明一个数字是素数,但可以任意降低误报的机会(低于运行确定性算法时出现硬件错误的概率)。
  • 谢谢。看起来 Miller Rabin 已经是本机 java 中的一个函数了!我只是不太明白。如果你能解释得更深入一点,不那么复杂,那就太好了我只是一个程序员,不是数学专业的。
【解决方案2】:

在 BigInteger 类中有一个方法叫做:

isProbablePrime(int)

它使用我们朋友使用的相同算法here: 但它也使用另一种算法检查结果。它工作得非常整洁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 2014-03-30
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多