【问题标题】:how to test a prime number 1000 digits long?如何测试 1000 位长的素数?
【发布时间】:2010-11-19 21:59:50
【问题描述】:

我正在尝试找出 1000 位长的数字是否为素数。我想使用的算法是 6k+/-1

我面临的问题是如何在 java 中存储这么长的数字,它将字符串作为输入。

做除数应该只考虑数字的最后几位。

请指教

【问题讨论】:

  • 你有足够的 CPU 能力来做这件事吗?这不是一件容易的事。
  • 您可能需要考虑使用已经存在的软件来执行此计算。如果您可以避免重新发明轮子,那么重新发明轮子是没有意义的,而且现有的软件很可能会胜过您自己的混合物。
  • 6k +/- 1 会告诉您它是否不是素数,或者它是否可能是素数。示例:k=6,35 不是素数。然而 723 == 3 (mod 6) 很快被确定为不是素数。如果 n == +-1 (mod 6),你仍然需要一个素数测试

标签: java algorithm


【解决方案1】:

我认为您可以将 BigInteger 用于非常大的数字。

但是,您应该注意一件事,格式为 6k+1 的所有数字都是质数。例如

when k=341,
6k +1 = 6(341) +1 = 2046 + 1= 2047

Now 2047 can be divided by 23 like so

2047/23 = 89 

因此在生成素数时使用它可能不是很好

【讨论】:

    【解决方案2】:

    如果您不是在寻找可编程方法,您也许应该问wolframalpha

    f.x: “是 1754179634151752538176965974334085811645204614256364837827967 一个素数”

    返回: “1754179634151752538176965974334085811645204614256364837827967 是质数!”

    【讨论】:

      【解决方案3】:

      如果您不喜欢概率方法,也可以使用deterministic polynomial algorithm

      但除非有神在玩赔率并拉扯你的腿或其他什么,你可能应该只使用概率方法,它们更快。

      【讨论】:

        【解决方案4】:

        您应该在基数 2 和 3 中使用 Lucas pseudoprime testRabin-Miller strong pseudoprime test。如果这三个都给出 可能是素数的结果,那么出于所有实际原因,您应该这样考虑。该测试没有已知的反例。如果您必须生成素数证书,则可以使用elliptic curve primality prover,但速度会非常慢。

        【讨论】:

        • 请注意,Java 的 isProbablePrime(int) 使用 Miller/Rabin- 和 Lucas/Lehmer 算法。
        • @Bart:记录在哪里?
        • @JasonS - 它在函数源代码上方的 cmets 中提到 :)
        • @xkcd -- 这不是文档。 (实际上,您刚刚回复了一条 6 年半的评论?)您必须查看依赖于实现的源代码才能看到它。 (例如 grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… 和私有的 passesMillerRabinpassesLucasLehmer 方法。
        【解决方案5】:

        如果确定一个数字是否可能是素数就足够了,您可以使用内置的isProbablePrime 函数

        • 如果调用返回真,则该数为素数的概率超过 (1 - 1/(2^certainty))。
        • 如果调用返回 false,则该数字肯定不是素数。

        【讨论】:

        • 嗯。我是唯一一个对 BigInteger 的可能素数方法的 javadoc 不包含有关使用哪种算法的文档感到非常不安的人吗?
        • @Jason - 为什么这会打扰你? javadoc 的目的是帮助 API 的用户知道如何使用它,而不是暴露内部实现细节。细节在源代码中写得很清楚。
        • 该函数运行得非常好而且速度很快,我将它与 gcd() 一起使用来不断分解一个存储两个 BigInt 的有理类来生成具有无限精度的有理数。它总是足够快地执行一些相当大的计算——即使是对两个由虚数组成的小矩阵进行运算,每个虚数都由两个 BigRational 数字组成——从用户的角度来看,大多数运算仍然几乎是瞬时的。
        • Here is the OpenJDK implementation for BigInteger#isProbablePrime(int certainty)。它调用包私有方法primeToCertainty(int certainty, Random random),然后使用passesMillerRabin(rounds, random)passesLucasLehmer();。这应该会给你一些线索:)
        【解决方案6】:

        6k +/- 1 不是素数测试!如果您已经知道数字 Q 是素数(并且更大 比 7),知道它的形式 6k +/- 1 告诉你它是否“安全”—— Q+1 和 Q-1 都有很大的因数,使得 Q 更难因数(因此对于加密目的来说是“安全的”)。但大多数 6k +/- 1 形式的数都是复合数。

        "Safe Prime" page from Wikipedia

        如果想编写自己的例程来测试 1000 位数字的素数,您需要使用 BigInteger 类,正如其他答案所建议的那样。你可以使用费马 首先测试,它会告诉你这个数字是“绝对合数”还是“可能是素数”。 然后,您可以使用计算量更大的测试,例如 Miller-Rabin 或 Solovay-Strassen 关于最终确定测试的“可能是素数”。

        Primality testing algorithms from Wikipedia

        【讨论】:

        • 所有大于 3 的素数都是 6k +/- 1 的形式。你是对的,因为它不是对素数的测试,但它是对素数的有效且相当快速的测试。如果 (p-1) % 6 ! 0 和 (p+1) % 6 != 0 那么这个数不是素数。是的,它会产生很多误报,但不会产生任何误报。
        【解决方案7】:

        你可以一起使用一些想法。

        • 算法 6k +/-1
        • 检查直到除数小于 sqrt(prime)
        • 仅检查除以素数

        结合这些方法,您可以大大加快验证速度。

        此链接可以帮助您: http://www.osix.net/modules/article/?id=791

        当然还要使用 BigInteger。

        【讨论】:

          【解决方案8】:

          一个 1000 位数字使用 BigDecimal 使用的内存少于 350 字节。您应该会发现您可以处理比这大得多的数字。

          你会发现的问题是你需要检查很多个数字,大约 10^31,这需要很长时间,大约 10^18 年。

          【讨论】:

            【解决方案9】:

            如果您需要处理 32/64 位空间之外的整数,您应该使用 BigInteger。不知道您是否需要担心实际限制。

            【讨论】:

              猜你喜欢
              • 2013-03-22
              • 2020-02-20
              • 1970-01-01
              • 2010-10-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-04-28
              相关资源
              最近更新 更多