我想更快地完成这段代码。它返回长数的所有因子(素数)。如果longNumber
是特定的,那么执行它显然需要几分钟。
int div = 2;
String factors = "";
while (longNumer != 1)
{
if (longNumer % div == 0)
{
longNumer /= div;
factors += div + " ";
}
else { div++; }
}
//longNumber = 10, gives: 2 5.
//longNumber = 150, gives: 3 5 7.
//longNumber = 10523, gives: 17 619.
这样的数字和#34; 7544222046562688368"需要太长时间,并且它不好,你会建议什么?
答案 0 :(得分:4)
对于大数字,您可以使用Sieve of Eratosthenes algorithm首先找到最大为sqrt(n)的素数,然后您必须检查这些素数是否是因子
答案 1 :(得分:2)
您可以使用以下步骤 -
1。查找所有素数< = sqrt(longNumber)。并将它们保存在一个数组中 - primes
2. 现在逐渐使用数组元素 - primes
作为除数来查找因子。
答案 2 :(得分:2)
表明Eratosthenes的筛子的答案对你描述的数字不会有太大作用。对于64
位数sqrt(2^64) = 2^32
,这仍然很多。
对于那些,您最好的赌注是Pollard's Rho algorithm或列出的更复杂的整数分解方法here:
代数群分解算法,其中包括Pollard的p - 1算法,Williams' p + 1算法和Lenstra椭圆曲线分解
费马的分解方法
Euler的分解方法
特殊号码筛子
答案 3 :(得分:2)
在比试验分割更快地实施其中一种保理算法之前,一个容易纠正的错误是避免在最后一块的sqrt之前进行试验分割。
while (longNumber != 1) {
if (longNumber % div == 0) {
longNumber /= div;
factors += div + " ";
}
else {
if (div*div>longNumber) {
if (longNumber > 1)
factors += longNumber + " ";
break; // leave the while loop.
}
div++;
}
}
让两个最大的素数因子是P1和P2。在您的版本中,您可以执行c P1操作。在修改后的版本中,您可以执行c Max(sqrt(P1),P2)。在7544222046562688368,改善应该是45倍。
另一个改进是改变div ++行。您不需要通过大于2的偶数进行试验除法,或者通过大于3的3除数。避免这些加速计算的速度超过另一个因子2,并且您可以通过避免稍微改善一下测试其他小素数的倍数。但是,你不想花时间用小素数进行div的试验分割。相反,你可以跟踪当前和允许的余数mod 2 * 3 * 5 * 7,比如说。这是使用轮子调用小素数。
其他一些答案谈到使用筛子找到所有小素数,然后仅使用试验除法。如果你只考虑一个数字,这没有任何帮助,因为它需要很长时间来筛选出素数。生成直到sqrt(n)的素数列表需要大约c sqrt(n)loglog n运算,而对于sqrt(n)的所有项的试验除法需要大约c sqrt(n)运算。如果您需要考虑许多大数字,那么执行一次筛选并存储结果可能会有所帮助。
答案 4 :(得分:1)
一个很好的方法来计算64位整数,它既简单编程又在实践中合理有效,结合了试验分区和Pollard的rho算法。这是伪代码:
function factors(n)
wheel := [1,2,2,4,2,4,2,4,6,2,6]
w, f, fs := 0, 2, []
while f*f <= n and f < 10000
while n % f == 0
fs, n := f :: fs, n / f
f, w := f + wheel[w], w+1
if w = 11 then w = 3
if n == 1 return fs
h, t, g, c := 1, 1, 1, 1
while not isPrime(n)
repeat
h := (h*h+c) % n # the hare runs
h := (h*h+c) % n # twice as fast
t := (t*t+c) % n # as the tortoise
g := gcd(t-h, n)
while g == 1
if isPrime(g)
while n % g == 0
fs, n := g :: fs, n / g
h, t, g, c := 1, 1, 1, c+1
return n :: fs
这使用2,3,5轮试验除以10000,然后简单实施rho算法;它应该在几毫秒内将您的样品编号计算为7544222046562688368 = 2 * 2 * 2 * 2 * 7 * 7 * 14618561 * 658254407。改进是可能的,但这应该足以让你开始。