主要因素为300亿?

时间:2009-01-13 16:59:45

标签: algorithm prime-factoring fxsl

我需要找出超过3000亿的主要因素。我有一个功能,正在添加到他们的列表......非常慢!它现在已经运行了大约一个小时,我认为它还有一段距离可以走了。我这样做是完全错误还是预期的?

编辑:我试图找到数字600851475143的最大素数因子。

编辑: 结果:

{
    List<Int64> ListOfPrimeFactors = new List<Int64>();
    Int64 Number = 600851475143;
    Int64 DividingNumber = 2;

    while (DividingNumber < Number / DividingNumber)
    {
        if (Number % DividingNumber == 0)
        {
            ListOfPrimeFactors.Add(DividingNumber);
            Number = Number/DividingNumber;
        }
        else
            DividingNumber++;
        }
        ListOfPrimeFactors.Add(Number);
        listBox1.DataSource = ListOfPrimeFactors;
    }
}

19 个答案:

答案 0 :(得分:25)

您是否还记得在找到每个因素时将您分解的数字除以?

比如说,你发现2是一个因素。您可以将其添加到因子列表中,然后将您尝试分解的数字除以该值。

现在你只是在寻找1500亿的因素。每次你应该从你刚刚找到的因素开始。因此,如果2是一个因素,再次测试2。如果您找到的下一个因素是3,则再次从2开始没有点测试。

等等......

答案 1 :(得分:20)

使用蛮力很难找到素因子,这听起来像你正在使用的技术。

以下是一些提高速度的提示:

  • 开始低,不高
  • 不要费心测试每个潜在因素以确定它是否为素数 - 只测试LIKELY素数(奇数以1,3,7或9结尾)
  • 不要打扰测试偶数(可以被2整除),或者以5结尾的几率(全部可以被5整除)。当然,实际上不要跳过2和5 !!
  • 当您找到一个主要因素时,请务必将其分开 - 不要继续使用您的大量原始号码。请参阅下面的示例。
  • 如果您找到一个因素,请务必再次测试它以查看它是否在那里多次。你的号码可能是2x2x3x7x7x7x31或类似的东西。
  • 当您达到&gt; = sqrt(剩余大号)
  • 时停止

编辑:一个简单的例子: 你找到了275的因素。

  1. 测试275的可除性为2. 275/2 = int(275/2)?没错。
  2. 测试275的可分性3.失败。
  3. 跳过4!
  4. 通过5测试275的可分性。是的! 275/5 = 55.所以你的新测试号现在是55。
  5. 测试 55 的可分性为5.是的! 55/5 = 11.所以你的新测试号现在是11。
  6. 但是5&gt; sqrt(11),所以11是素数,你可以停下来!
  7. 所以275 = 5 * 5 * 11

    更有意义吗?

答案 2 :(得分:17)

保理大数字是一个难题。事实上,我们很难依靠它来保证RSA的安全。但是请看一下wikipedia page以获得可以提供帮助的算法的一些指示。但对于一个小的数字,它真的不应该花那么长时间,除非你一遍又一遍地重新做一些你没有去过的地方。

对于蛮力解决方案,请记住您可以进行一些小优化:

  • 特别检查2,然后只检查奇数。
  • 你只需要检查数字的平方根(如果你找不到因子,那么数字是素数)。
  • 找到因素后,请勿使用原始数字查找下一个因子,将其除以找到的因子,然后搜索新的较小数字。
  • 当您找到一个因子时,尽可能多地将其除以。之后,您再也不需要检查该号码或任何较小的号码。
  • 如果您执行以上所有操作,您找到的每个新因素都将成为素数,因为任何较小的因素都已被删除。

答案 3 :(得分:10)

这是一个XSLT解决方案!

此XSLT转换需要0.109秒

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:saxon="http://saxon.sf.net/"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="xs saxon f"
 >
 <xsl:import href="../f/func-Primes.xsl"/>

 <xsl:output method="text"/>


 <xsl:template name="initial" match="/*">
   <xsl:sequence select="f:maxPrimeFactor(600851475143)"/>
 </xsl:template>

 <xsl:function name="f:maxPrimeFactor" as="xs:integer">
   <xsl:param name="pNum" as="xs:integer"/>

   <xsl:sequence select=
    "if(f:isPrime($pNum))
       then $pNum
       else
         for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
             $vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
             $vDiv2 in $pNum idiv $vDiv1
           return 
             max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
    "/>
 </xsl:function>
</xsl:stylesheet>

此转换仅在0.109秒内产生正确的结果(最大素数因子600851475143)。

<强> 6857

转换使用f:sqrt()中定义的f:isPrime()FXSL 2.0 - XSLT中的函数式编程库。 FXSL本身完全由XSLT撰写。

f:isPrime() 使用Fermat's little theorem,因此确定原则是有效的。

答案 4 :(得分:3)

没人提到的最后一件事,也许是因为它显而易见。每次找到一个因子并将其分解出来时,请继续尝试该因子直至其失败。

64只有一个素数因子,2。如果你继续将2除去,你将会发现它非常简单。

答案 5 :(得分:2)

$ time factor 300000000000 > /dev/null

real        0m0.027s
user        0m0.000s
sys         0m0.001s

如果需要一个小时,你就会做错事。你甚至可能在某个地方有一个无限循环 - 确保你没有使用32位整数。

答案 6 :(得分:2)

理解平方根为什么重要的关键,考虑n 低于 n的平方根的每个因子都有一个相应的因子高于它。要看到这一点,考虑如果x是因子n,则x / n = m,这意味着x / m = n,因此m也是一个因子。

答案 7 :(得分:1)

具体数量是300425737571?它简单地分为131 * 151 * 673 * 22567。 我不明白所有的大惊小怪......

答案 8 :(得分:1)

我不希望它花费很长时间 - 这不是一个特别大的数字。

你能给我们一个导致代码困难的示例号码吗?

答案 9 :(得分:1)

以下是Haskell对你们的好处:)

primeFactors n = factor n primes
  where factor n (p:ps) | p*p > n = [n]
                        | n `mod` p /= 0 = factor n ps
                        | otherwise = p : factor (n `div` p) (p:ps)
        primes = 2 : filter ((==1) . length . primeFactors) [3,5..]

花了大约0.5秒才找到它们,所以我称之为成功。

答案 10 :(得分:1)

这是一个可以获得答案的网站:Factoris - Online factorization service。它可以做很大的数字,但它也可以分解代数表达式。

答案 11 :(得分:1)

最快的算法是筛选算法,它基于离散数学的神秘领域(至少在我的头上),实现和测试复杂。

最简单的保理算法可能(正如其他人所说的那样)是Eratosthenes的筛子。要记住使用它来计算数字N

的事情
  • 一般想法:您正在检查可能的整数因子x的增加序列,以查看它们是否均匀划分您的候选号N(在C / Java / Javascript中检查是否N % x == 0 )在这种情况下,N不是素数。
  • 您只需要前往sqrt(N),但只要测试因子x通过测试sqrt(N)
  • ,就不会实际计算x*x<N:循环
  • 如果你有内存来保存一堆以前的素数,只使用那些作为测试因子(如果素数P未通过测试P*P > N_max则不要保存它们,因为你永远不会再使用它们< / LI>
  • 即使您不保存以前的素数,对于可能的因素x,只需检查2和所有奇数。是的,它需要更长的时间,但对于合理大小的数字而言则不会那么长。 prime-counting function及其近似值可以告诉您哪些数字是素数;这个分数慢慢减少非常。即使对于2 64 =约1.8x10 19 ,每43个数字中大约有一个是素数(=每21.5个奇数中有一个是素数)。对于小于2 64 的数字因子,那些因子x小于2 32 其中每20个数字中约有一个是素数=每个中有一个10个奇数是素数。所以你必须测试10倍的数字,但循环应该更快一点,你不必乱用存储所有这些素数。

还有一些更老,更简单的筛选算法,有点复杂但仍然可以理解。请参阅Dixon'sShanks'Fermat's分解算法。我读过一篇关于其中一篇的文章,不记得是哪一篇,但它们都相当简单,并且使用了正方形差异的代数属性。

如果您只是测试一个数字N是否为素数,而您实际上并不关心这些因素,请使用probabilistic primality test。我认为Miller-Rabin是最标准的一个。

答案 12 :(得分:1)

我花了一些时间在这上面,因为它只是吸引我。我不会在这里粘贴代码。如果您感到好奇,请参阅this factors.py gist

请注意,在阅读这个问题之前,我对保理(仍然没有)知之甚少。它只是上面BradC答案的Python实现。

在我的MacBook上,需要0.002秒来计算问题中提到的数字(600851475143)。

显然必须有更多,更快的方法。我的程序需要19秒来计算6008514751431331的因子。但是Factoris服务只是在没有时间的情况下吐出答案。

答案 13 :(得分:0)

你只需要检查它的余数mod(n),其中n是素数&lt; = sqrt(N),其中N是你想要考虑的数字。它真的不应该花费超过一个小时,即使在非常慢的计算机或TI-85上。

答案 14 :(得分:0)

只是为了扩大/改善“仅测试不以5结尾的奇数”建议......

所有大于3的素数要比6的倍数多一个或少一个(对于x的整数值为6x + 1或6x - 1)。

答案 15 :(得分:0)

您的算法必须是FUBAR。在我的1.6 GHz上网本中,这只需要大约0.1秒。 Python并不以其超快的速度而闻名。但它确实有任意精度整数...

import math
import operator

def factor(n):
    """Given the number n, to factor yield a it's prime factors.
    factor(1) yields one result: 1. Negative n is not supported."""
    M = math.sqrt(n)  # no factors larger than M
    p = 2             # candidate factor to test
    while p <= M:     # keep looking until pointless
        d, m = divmod(n, p)
        if m == 0:
            yield p   # p is a prime factor
            n = d     # divide n accordingly
            M = math.sqrt(n)  # and adjust M
        else:
            p += 1    # p didn't pan out, try the next candidate
    yield n  # whatever's left in n is a prime factor

def test_factor(n):
    f = factor(n)
    n2 = reduce(operator.mul, f)
    assert n2 == n

def example():
    n = 600851475143
    f = list(factor(n))
    assert reduce(operator.mul, f) == n
    print n, "=", "*".join(str(p) for p in f)

example()

# output:
# 600851475143 = 71*839*1471*6857

(这段代码似乎无视我不太了解数论以填补顶针这一事实。)

答案 16 :(得分:0)

您可以使用sieve of Eratosthenes查找素数并查看您的号码是否可以被您找到的那些整除。

答案 17 :(得分:-1)

该大小的半素数用于加密,所以我很想知道你究竟想用它们做什么。

除此之外,目前还没有很好的方法可以在相对较短的时间内找到大数的素数因子化。

答案 18 :(得分:-1)

即使使用相对天真的蛮力,也不应该花那么长时间。对于那个特定的数字,我可以在大约一秒钟内考虑它。

你说你不想要解决方案(?),但这是你的“微妙”暗示。这个数字唯一的主要因素是最低的三个素数。