改进以更快的方式分解的代码?

时间:2015-03-30 20:17:03

标签: java algorithm math optimization factorization

我想更快地完成这段代码。它返回长数的所有因子(素数)。如果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"需要太长时间,并且它不好,你会建议什么?

5 个答案:

答案 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。改进是可能的,但这应该足以让你开始。