我需要找出超过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;
}
}
答案 0 :(得分:25)
您是否还记得在找到每个因素时将您分解的数字除以?
比如说,你发现2是一个因素。您可以将其添加到因子列表中,然后将您尝试分解的数字除以该值。
现在你只是在寻找1500亿的因素。每次你应该从你刚刚找到的因素开始。因此,如果2是一个因素,再次测试2。如果您找到的下一个因素是3,则再次从2开始没有点测试。
等等......
答案 1 :(得分:20)
使用蛮力很难找到素因子,这听起来像你正在使用的技术。
以下是一些提高速度的提示:
编辑:一个简单的例子: 你找到了275的因素。
所以275 = 5 * 5 * 11
更有意义吗?
答案 2 :(得分:17)
保理大数字是一个难题。事实上,我们很难依靠它来保证RSA的安全。但是请看一下wikipedia page以获得可以提供帮助的算法的一些指示。但对于一个小的数字,它真的不应该花那么长时间,除非你一遍又一遍地重新做一些你没有去过的地方。
对于蛮力解决方案,请记住您可以进行一些小优化:
答案 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 > 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's,Shanks'和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)
即使使用相对天真的蛮力,也不应该花那么长时间。对于那个特定的数字,我可以在大约一秒钟内考虑它。
你说你不想要解决方案(?),但这是你的“微妙”暗示。这个数字唯一的主要因素是最低的三个素数。