【问题标题】:Prime Factorization in AndroidAndroid中的素数分解
【发布时间】:2014-12-27 15:27:45
【问题描述】:

我正在为 Android 设备开发一个小型素数应用程序,并且快完成了,但是我需要一些帮助来优化我的因式分解类。

我仍然有一个或两个问题,一些大数(偶数)在合理的时间内被分解。我将无法在这个特定项目中使用 Eratosthenes 的筛子,因为我最多只能筛出 1000 万个,而应用程序不会在我的物理设备(三星 Galaxy S4 Mini)上崩溃。所以我的算法工作如下。我不确定是否可以使我实现的 Pollard Rho 算法更好。

一旦我确定要测试的数字不是质数或不是质数平方,我会迅速进行高达 10 000 的试除法,然后如果该数字仍未完全分解,我会使用 Pollard Rho方法来减少它的其余部分。

我希望能够分解 2 > 2^64 范围内的数字。

这是一个大约需要 15 秒的数字示例 256332652145852

它的因式分解是 [2, 2, 1671053, 38348971]。

任何帮助将不胜感激。

try {
        long num = Long.valueOf(input);
        if(num == 1) {
            return "1" + " = " + input;
        } else if(num < 1) {
            return "Cannot factor a number less than 1";
        } else if(PrimeNumbers.isPrime(num) == true) {
            return result = num + " is a Prime Number.";
        } else if(isSquare(num) == true && PrimeNumbers.isPrime((long) Math.sqrt(num)) == true) {

            return result = (int) Math.sqrt(num) + "<sup><small>" + 2 + "</small></sup>" + " = " + input;

        } else {
            factors(num, pFactors);
            return result = exponentialForm(pFactors, num) + " = " + input;
        }
    } catch(NumberFormatException e) {
        return result = "Unfortunately the number entered is too large";
    }
}

public static void factors(long n, ArrayList<Long> arr) {

    long number = trialDiv(n, arr);
    if(number > 1) {
        while(true) {
            long divisor = pollard(number, 1);
            if(PrimeNumbers.isPrime(divisor) == true) {
                number /= divisor;
                arr.add(divisor);
                if(PrimeNumbers.isPrime(number) == true) {
                    arr.add(number);
                    break;
                }
            }
        }
    }
}

private static long trialDiv(long n, ArrayList<Long> arr) {

    while(n % 2 == 0) {
        n /= 2;
        arr.add((long) 2);
    }

    for(long i = 3; i < 10000; i += 2) {
        if(PrimeNumbers.isPrime(i) == true) {
            while(n % i == 0) {
                arr.add(i);
                n /= i;
            }
        }
    }
    if(PrimeNumbers.isPrime(n) == true) {
        arr.add(n);
        return 1;
    }
    return n;
}

public static long pollard(long n, long c) {

    long x = 2;
    long y = 2;
    long d = 1;

    while (d == 1) {
        x = g(x, n, c);
        y = g(g(y, n, c), n, c);
        d = gcd(Math.abs(y - x), n);
    }

    if (d == n) {
        return pollard(n, c + 1);
    } else {
        return d;
    }
}

static long g(long x, long n, long c) {
    long g = (((x * x) + c) % n);
    return g;
}

static long gcd(long a, long b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

【问题讨论】:

  • factors(num, pFactors); 不输出任何东西和它的调用函数有什么用?
  • 有一个全局声明的 ArrayList,factors 方法及其方法添加到其中。对不起,如果这没有任何意义。
  • 这个问题很适合codereview.stackexchange.com

标签: android algorithm prime-factoring


【解决方案1】:

您的 pollard 函数还可以,但不是很好。您正在使用 Pollard 的原始算法,但最好使用 Brent 的变体。但这可能不是您性能缓慢的原因。

您的试用部门功能很慢。检查每个可能的除数的素数非常昂贵,而且没有必要。是否除以复合并不重要。除法总是会失败,但你不要浪费时间检查素数。更好的方法是车轮分解。

【讨论】:

  • 感谢您抽出宝贵时间发表评论,我将从试除法中删除素数检查。并将开始研究车轮分解。
猜你喜欢
  • 2014-07-11
  • 2014-07-03
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-20
相关资源
最近更新 更多