300 000 000 000 的质因数?

发布于 2024-07-11 09:02:37 字数 703 浏览 6 评论 0 原文

我需要找出超过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;
    }
}

I need to find out the prime factors of over 300 billion. I have a function that is adding to the list of them...very slowly! It has been running for about an hour now and i think its got a fair distance to go still. Am i doing it completly wrong or is this expected?

Edit: Im trying to find the largest prime factor of the number 600851475143.

Edit:
Result:

{
    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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

殤城〤 2024-07-18 09:02:38

您只需要检查它的余数 mod(n),其中 n 是素数 <= sqrt(N),其中 N 是您要分解的数字。 即使在非常慢的计算机或 TI-85 上,它实际上也不应该花费一个多小时。

You only need to check it's remainder mod(n) where n is a prime <= sqrt(N) where N is the number you are trying to factor. It really shouldn't take over an hour, even on a really slow computer or a TI-85.

流年里的时光 2024-07-18 09:02:38

你的算法必须是FUBAR。 在我使用 Python 的 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

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

Your algorithm must be FUBAR. This only takes about 0.1s on my 1.6 GHz netbook in Python. Python isn't known for its blazing speed. It does, however, have arbitrary precision integers...

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

(This code seems to work in defiance of the fact that I don't know enough about number theory to fill a thimble.)

绝影如岚 2024-07-18 09:02:38

只是为了稍微扩展/改进“仅测试不以 5 结尾的奇数”建议...

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

Just to expand/improve slightly on the "only test odd numbers that don't end in 5" suggestions...

All primes greater than 3 are either one more or one less than a multiple of 6 (6x + 1 or 6x - 1 for integer values of x).

猫烠⑼条掵仅有一顆心 2024-07-18 09:02:38

即使使用相对简单的蛮力,也不应该花那么长时间。 对于这个具体数字,我可以在大约一秒钟的时间内在脑海中将其分解。

你说你不需要解决方案(?),但这是你的“微妙”提示。 该数字的唯一质因数是最低的三个质数。

It shouldn't take that long, even with a relatively naive brute force. For that specific number, I can factor it in my head in about one second.

You say you don't want solutions(?), but here's your "subtle" hint. The only prime factors of the number are the lowest three primes.

我做我的改变 2024-07-18 09:02:38

该大小的半素数用于加密,所以我很好奇你到底想用它们做什么。

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

Semi-prime numbers of that size are used for encryption, so I am curious as to what you exactly want to use them for.

That aside, there currently are not good ways to find the prime factorization of large numbers in a relatively small amount of time.

辞旧 2024-07-18 09:02:37

您是否记得将要因式分解的数字除以找到的每个因数?

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

现在您只需搜索 1500 亿的因数。 每次你都应该从你刚刚找到的因素开始。 因此,如果 2 是一个因素,请再次测试 2。 如果您找到的下一个因子是 3,则无需再次从 2 进行测试。

等等...

Are you remembering to divide the number that you're factorizing by each factor as you find them?

Say, for example, you find that 2 is a factor. You can add that to your list of factors, but then you divide the number that you're trying to factorise by that value.

Now you're only searching for the factors of 150 billion. Each time around you should start from the factor you just found. So if 2 was a factor, test 2 again. If the next factor you find is 3, there's no point testing from 2 again.

And so on...

焚却相思 2024-07-18 09:02:37

使用蛮力查找素因数很困难,这听起来像是您正在使用的技术。

这里有一些加快速度的技巧:

  • 从低开始,而不是从高开始
  • 不要费心去测试每个潜在的因子来看看它是否是素数——只需测试类似的素数(以 1、3、7 或 9 结尾的奇数) )
  • 不要费心去测试偶数(都可以被 2 整除),或者以 5 结尾的赔率(都可以被 5 整除)。 当然,实际上不要跳过 2 和 5!
  • 当你找到一个质因数时,一定要把它除掉——不要继续使用你的大量原始数字。 请参阅下面我的示例。
  • 如果您发现某个因素,请务必再次测试它,看看它是否存在多次。 您的号码可能是 2x2x3x7x7x7x31 或类似的数字。
  • 当达到>= sqrt(剩余大数)时停止

编辑:一个简单的例子:
您正在查找 275 的因数。

  1. 测试 275 能否被 2 整除。275/2 = int(275/2) 吗? 不,失败了。
  2. 测试 275 能否被 3 整除。失败。
  3. 跳过4!
  4. 测试 275 能否被 5 整除。是的! 275/5 = 55。所以您的新测试数现在是 55。
  5. 测试 55 是否能被 5 整除。是的! 55/5 = 11。所以您的新测试编号现在是 11。
  6. 但是 5 > sqrt (11),所以 11 是素数,你可以停下来了!

那么 275 = 5 * 5 * 11

更有意义吗?

Finding prime factors is difficult using brute force, which sounds like the technique you are using.

Here are a few tips to speed it up somewhat:

  • Start low, not high
  • Don't bother testing each potential factor to see whether it is prime--just test LIKELY prime numbers (odd numbers that end in 1,3,7 or 9)
  • Don't bother testing even numbers (all divisible by 2), or odds that end in 5 (all divisible by 5). Of course, don't actually skip 2 and 5!!
  • When you find a prime factor, make sure to divide it out--don't continue to use your massive original number. See my example below.
  • If you find a factor, make sure to test it AGAIN to see if it is in there multiple times. Your number could be 2x2x3x7x7x7x31 or something like that.
  • Stop when you reach >= sqrt(remaining large number)

Edit: A simple example:
You are finding the factors of 275.

  1. Test 275 for divisibility by 2. Does 275/2 = int(275/2)? No. Failed.
  2. Test 275 for divisibility by 3. Failed.
  3. Skip 4!
  4. Test 275 for divisibility by 5. YES! 275/5 = 55. So your NEW test number is now 55.
  5. Test 55 for divisibility by 5. YES! 55/5 = 11. So your NEW test number is now 11.
  6. BUT 5 > sqrt (11), so 11 is prime, and you can stop!

So 275 = 5 * 5 * 11

Make more sense?

﹎☆浅夏丿初晴 2024-07-18 09:02:37

对大数进行因式分解是一个难题。 事实上,如此困难以至于我们依赖它来保证 RSA 的安全。 但请查看维基百科页面,了解一些可以提供帮助的算法指针。 但对于这么小的数字,确实不应该花那么长时间,除非您一遍又一遍地重复工作,而不必在某个地方做。

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

  • 专门检查 2,然后仅检查奇数。
  • 您只需要检查数字的平方根(如果此时没有找到因数,则该数字是质数)。
  • 一旦找到一个因子,不要使用原始数字来查找下一个因子,而是将其除以找到的因子,然后搜索新的较小数字。
  • 当你找到一个因子时,将其除以尽可能多的次数。 之后,您再也不需要检查该数字或任何较小的数字。
  • 如果您执行上述所有操作,您找到的每个新因子都将是素数,因为任何较小的因子都已被删除。

Factoring big numbers is a hard problem. So hard, in fact, that we rely on it to keep RSA secure. But take a look at the wikipedia page for some pointers to algorithms that can help. But for a number that small, it really shouldn't be taking that long, unless you are re-doing work over and over again that you don't have to somewhere.

For the brute-force solution, remember that you can do some mini-optimizations:

  • Check 2 specially, then only check odd numbers.
  • You only ever need to check up to the square-root of the number (if you find no factors by then, then the number is prime).
  • Once you find a factor, don't use the original number to find the next factor, divide it by the found factor, and search the new smaller number.
  • When you find a factor, divide it through as many times as you can. After that, you never need to check that number, or any smaller numbers again.
  • If you do all the above, each new factor you find will be prime, since any smaller factors have already been removed.
ぶ宁プ宁ぶ 2024-07-18 09:02:37

这是一个 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 —— XSLTFXSL 本身完全是用 XSLT

f:isPrime() 使用< strong>费马小定理,从而可以高效地确定素性。

Here is an XSLT solution!

This XSLT transformation takes 0.109 sec.

<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>

This transformation produces the correct result (the maximum prime factor of 600851475143) in just 0.109 sec.:

6857

The transformation uses the f:sqrt() and f:isPrime() defined in FXSL 2.0 -- a library for functional programming in XSLT. FXSL is itself written entirely in XSLT.

f:isPrime() uses Fermat's little theorem so that it is efficient to determine primeality.

心房敞 2024-07-18 09:02:37

最后一件事没有人提到,也许是因为它看起来很明显。 每次找到一个因子并将其除掉时,不断尝试该因子,直到失败为止。

64 只有一个质因数 2。如果你不断地除 2 直到你不能除为止,你会发现这个结果非常微不足道。

One last thing nobody has mentioned, perhaps because it seems obvious. Every time you find a factor and divide it out, keep trying the factor until it fails.

64 only has one prime factor, 2. You will find that out pretty trivially if you keep dividing out the 2 until you can't anymore.

再见回来 2024-07-18 09:02:37
$ time factor 300000000000 > /dev/null

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

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

$ time factor 300000000000 > /dev/null

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

You're doing something wrong if it's taking an hour. You might even have an infinite loop somewhere - make sure you're not using 32-bit ints.

归途 2024-07-18 09:02:37

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

The key to understanding why the square root is important, consider that each factor of n below the square root of n has a corresponding factor above it. To see this, consider that if x is factor of n, then x/n = m which means that x/m = n, hence m is also a factor.

梦屿孤独相伴 2024-07-18 09:02:37

我根本不认为它会花费很长时间——这并不是一个特别大的数字。

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

I wouldn't expect it to take very long at all - that's not a particularly large number.

Could you give us an example number which is causing your code difficulties?

笑看君怀她人 2024-07-18 09:02:37

您可以在以下网站上获得答案:Factoris - 在线分解服务。 它可以计算非常大的数字,但它也可以分解代数表达式。

Here's one site where you can get answers: Factoris - Online factorization service. It can do really big numbers, but it also can factorize algebraic expressions.

温柔一刀 2024-07-18 09:02:37

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

最简单的因式分解算法可能是(正如其他人所说的)埃拉托斯特尼筛法。 使用此方法来分解数字 N 时需要记住的事情:

  • 总体思路:您正在检查可能的整数因子 x 的递增序列,看看它们是否能均匀地划分您的候选数字N(在 C/Java/Javascript 中检查是否 N % x == 0),在这种情况下 N 不是素数。
  • 您只需要上升到 sqrt(N),但实际上并不计算 sqrt(N):只要您的测试因子 x 通过测试即可循环 x*x
  • 如果您有足够的内存来保存一堆以前的素数,请仅使用它们作为测试因子(如果素数 P 未通过测试,则不要保存它们P*P > ; N_max 因为你永远不会再使用它们
  • 即使你不保存以前的素数,对于可能的因子 x 只需检查 2 和所有奇数 是的,它会花费。更长,但对于合理大小的数字来说,时间不会太长。它的近似值可以告诉您哪些数字是质数;即使对于 264 = 大约 1.8x1019,该分数的减小也非常。每 43 个数字中就有一个是素数(= 每 21.5 个奇数中就有一个是素数)对于小于 264 的因数,这些因数 x 小于。 232 其中大约每 20 个数字中有一个是质数 = 每 10 个奇数中有一个是质数。 因此,您必须测试 10 倍的数字,但循环应该更快一些,而且您不必费力存储所有这些素数。

还有一些较旧且更简单的筛选算法,它们稍微复杂一些,但仍然相当容易理解。 请参阅迪克森Shanks'费马的< /a> 因式分解算法。 我读过一篇关于其中一篇的文章,不记得是哪一篇了,但它们都相当简单,并且使用平方差的代数性质。

如果您只是测试数字 N 是否是素数,并且实际上并不关心因子本身,请使用 概率素性测试。 我认为 Miller-Rabin 是最标准的。

The fastest algorithms are sieve algorithms, and are based on arcane areas of discrete mathematics (over my head at least), complicated to implement and test.

The simplest algorithm for factoring is probably (as others have said) the Sieve of Eratosthenes. Things to remember about using this to factor a number N:

  • general idea: you're checking an increasing sequence of possible integer factors x to see if they evenly divide your candidate number N (in C/Java/Javascript check whether N % x == 0) in which case N is not prime.
  • you just need to go up to sqrt(N), but don't actually calculate sqrt(N): loop as long as your test factor x passes the test x*x<N
  • if you have the memory to save a bunch of previous primes, use only those as the test factors (and don't save them if prime P fails the test P*P > N_max since you'll never use them again
  • Even if you don't save the previous primes, for possible factors x just check 2 and all the odd numbers. Yes, it will take longer, but not that much longer for reasonable sized numbers. The prime-counting function and its approximations can tell you what fraction of numbers are prime; this fraction decreases very slowly. Even for 264 = approx 1.8x1019, roughly one out of every 43 numbers is prime (= one out of every 21.5 odd numbers is prime). For factors of numbers less than 264, those factors x are less than 232 where about one out of every 20 numbers is prime = one out of every 10 odd numbers is prime. So you'll have to test 10 times as many numbers, but the loop should be a bit faster and you don't have to mess around with storing all those primes.

There are also some older and simpler sieve algorithms that a little bit more complex but still fairly understandable. See Dixon's, Shanks' and Fermat's factoring algorithms. I read an article about one of these once, can't remember which one, but they're all fairly straightforward and use algebraic properties of the differences of squares.

If you're just testing whether a number N is prime, and you don't actually care about the factors themselves, use a probabilistic primality test. Miller-Rabin is the most standard one, I think.

一页 2024-07-18 09:02:37

我花了一些时间在这上面,因为它让我着迷。我暂时不会将代码粘贴到这里。 如果您好奇的话,请参阅this Factors.py gist

请注意,在阅读这个问题之前,我对因式分解一无所知(现在仍然不知道)。 这只是 BradC 上面答案的 Python 实现。

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

显然必须有更多、更快的方法来做到这一点。 我的程序需要 19 秒来计算 6008514751431331 的因子。但是 Factoris 服务立即给出答案。

I spent some time on this since it just sucked me in. I won't paste the code here just yet. Instead see this factors.py gist if you're curious.

Mind you, I didn't know anything about factoring (still don't) before reading this question. It's just a Python implementation of BradC's answer above.

On my MacBook it takes 0.002 secs to factor the number mentioned in the question (600851475143).

There must obviously be much, much faster ways of doing this. My program takes 19 secs to compute the factors of 6008514751431331. But the Factoris service just spits out the answer in no-time.

紫轩蝶泪 2024-07-18 09:02:37

具体号码是300425737571? 它很简单地分解为 131 * 151 * 673 * 22567。
我不明白有什么大惊小怪的...

The specific number is 300425737571? It trivially factors into 131 * 151 * 673 * 22567.
I don't see what all the fuss is...

柠檬色的秋千 2024-07-18 09:02:37

这里有一些 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 秒找到它们,所以我认为这是成功的。

Here's some Haskell goodness for you guys :)

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..]

Took it about .5 seconds to find them, so I'd call that a success.

樱娆 2024-07-18 09:02:37

您可以使用埃拉托斯特尼筛来查找素数,看看您的数字是否能被这些素数整除你发现。

You could use the sieve of Eratosthenes to find the primes and see if your number is divisible by those you find.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文