【问题标题】:Python app to make a random prime number between 10^300 and 10^301Python 应用程序在 10^300 和 10^301 之间生成随机素数
【发布时间】:2011-04-12 06:55:54
【问题描述】:

我需要让 Python 应用程序在 10^300 和 10^301 之间生成一个随机素数,我这样做了,但它非常慢。有什么解决办法吗?


import random , math
check_prime = 0

print "Please wait ..." def is_prime(n): import math n = abs(n) i = 2 while i <= math.sqrt(n): if n % i == 0: return False i += 1
return True

while check_prime == 0 : randomnumber = random.randrange(math.pow(10,300),math.pow(10,301)-1) if is_prime(randomnumber): print randomnumber break

【问题讨论】:

  • 预先计算 10^300 和 10^301 之间的所有素数,将此列表添加到您的代码中并从该列表中选择一个素数?
  • 你说它“很慢”? math.sqrt 任何大于 10^300 的数字至少是 10^150。如果我的计算机需要 25 毫秒来迭代 xrange(1000000)(等于 10^6)并且什么都不做,那么它需要大约 10^130 个年龄来迭代超过 10^150 个数字。因此,除了is_prime 实现之外,可能还有其他方法可以检查素数。
  • @Ocaso:在 10^300 和 10^301 之间有 9000000000000000000000000000000(加上另外 270 个零)数字。如果它们中只有十亿分之一是质数,它仍然无法放入 RAM。
  • 谁给了@Ocaso 不少于五个向上箭头的评论?使用this 信息,我估计他建议的列表将包含 Li(10^301) - Li(10^300) = 1.3 * 10^298 项。请记住,可见宇宙估计包含大约 10^80 个原子。 Wikipedia 指出,检查这个数量级的一个数的素数所需的估计操作数是 log(10^300)^6 = 1.1 * 10^17,大约需要 1.1e17 / 160E9 / 60^2 =在 160 000 MIPS CPU 上运行 190 小时。
  • @lazyr, @eumiro(顺便说一句:我给你们两个都投了赞成票):我知道在那个范围内处理 all 素数是不可能的,但@ShirazITCo 没有t 说他的问题的用例是什么。在某些情况下,最好有一个经过计算的素数列表。

标签: python random


【解决方案1】:

首先要做的是:不要使用 math.pow(),因为它只是 C 浮点函数的包装器,而且您的数字太大而无法准确地表示为浮点数。使用 Python 的指数运算符,即 **。

第二:如果您在具有gmpy 版本的平台上,请使用该版本进行素性测试。

第三:正如 eumiro 所说,您可能正在处理太大的问题空间,以至于没有任何真正快速的解决方案。

【讨论】:

    【解决方案2】:

    如果您需要快速而肮脏的东西,只需使用费马小定理。

    def isPrime(p):
        if(p==2): return True
        if(not(p&1)): return False
        return pow(2,p-1,p)==1
    

    虽然这对于随机数非常有效,但对于称为“伪素数”的数字会失败。 (相当稀缺) 但是,如果您需要一些万无一失且足够简单来实现的东西,我建议您 阅读有关 Miller Rabin 的素性检验的信息。

    PS: pow(a,b,c) 在 python 中需要 O(log(b)) 时间。

    【讨论】:

    • 以 2 为基数的伪素数(您的代码会错误地报告为素数)并不罕见。直到 2000 的整数中有 7 个。所以如果你真的需要一个素数,这个测试可能还不够。
    • 这可能又快又脏,但我对它的测试表明它实际上相当快。
    【解决方案3】:

    看看Miller-Rabin test我相信你会在网上找到一些Python的实现。

    【讨论】:

      【解决方案4】:

      正如 cmets 中所解释的,您可以忘记构建 10^300 到 10^301 之间所有素数的列表并随机选择一个 - 该范围内的素数数量级太多,无法正常工作。

      据我所知,唯一实用的方法是从范围中随机选择一个数字,然后测试它是否为素数。重复直到找到一个素数。

      对于素数测试,这本身就是一个完整的主题(图书馆 [在书本意义上] 已经写过关于它的文章)。基本上,您首先进行一些快速测试以丢弃显然不是素数的数字,然后拿出大枪并使用常见的素数测试之一(Miller-Rabin(迭代),AKS,...)。我知道的不够多,无法推荐,但这确实是研究级数学的话题,所以你应该去https://math.stackexchange.com/

      参见例如这个问题作为一个起点和一些简单的食谱:

      How do you determine if a number is prime or composite?

      关于你的代码:

      你发布的代码基本上和我描述的一样,但是它使用了一个非常简单的素数测试(试验除以所有数字 1...sqrt(n))。这就是为什么它这么慢。如果您使用更好的素性测试,它会快几个数量级。

      【讨论】:

        【解决方案5】:

        由于您要处理非常大的数字,因此您应该真正建立在聪明人已经为您完成的基础之上。鉴于您需要确定您的数字是素数(米勒拉宾出局),并且您确实想要一个 随机 素数(不是特定结构),我建议AKS。我不确定如何优化被测数字,但考虑到素数测试的速度,只选择一个随机数可能没问题。

        【讨论】:

        • 为什么米勒-拉宾出局了?您可以经常重复测试以获得极低的错误概率(我相信这是大多数生产质量的加密软件所做的)。当然,AKS 也可以工作。不知道在实践中什么更快。
        【解决方案6】:

        如果您想生成大量素数,或快速生成它们,纯 python 可能不是可行的方法 - 一种选择是使用 python openssl 包装器,并使用 openssl 的工具来生成 RSA 私钥(它们实际上是一对素数),或一些openssl的其他素数相关函数。实现速度的另一种方法是实现以下测试之一的 C 扩展...

        如果 opessl 不是一个选项,您的两个选择(正如许多 cmets 所提到的)是 Miller-Rabin 测试和 AKS 测试。主要区别 - AKS 是确定性的,并且保证不会给出错误的结果;而 Miller-Rabin 是概率性的,它可能偶尔会给出误报 - 但运行时间越长,概率就越低(k 轮测试的几率为 1/4**k)。你会认为 AKS 显然是要走的路,除了它要慢得多 - O(log(n)**12) 与 Miller-Rabin 的 O(k*log(n)**3) 相比。 (作为比较,您提供的扫描测试将采用O(n**.5),因此对于大数字,这两种方法中的任何一种都会快得多

        如果有用,我可以粘贴我拥有的 Miller-Rabin 实现,但它相当长。

        【讨论】:

          【解决方案7】:

          使用不同的算法可能会更好,但您也可以很容易地优化此代码。

          这个函数会快一倍:

          def is_prime(n):
              import math
              n = abs(n)
              if n % 2 == 0:
                  return False
              i = 3
              while i <= math.sqrt(n):
                  if n % i == 0:
                      return False
                  i += 2
          
              return True
          

          【讨论】:

          • @eumiro,我认为两倍的速度仍然有帮助。如果我可以制作任何脚本,只需添加/更改 3 行,我的运行速度就会提高一倍,我将是一个非常快乐的人。
          • 是的,通常是这样。但是,eurmiro 指出,如果您的预期运行时间长于宇宙热寂之前的预期时间,那么两倍的速度对您没有帮助......
          猜你喜欢
          • 2011-08-10
          • 1970-01-01
          • 1970-01-01
          • 2013-12-21
          • 2014-12-09
          • 2020-08-11
          • 2016-06-03
          • 2017-03-12
          相关资源
          最近更新 更多