【问题标题】:Better way to find all the prime factors of huge integers in C?在C中找到大整数的所有质因子的更好方法?
【发布时间】:2020-04-20 01:49:35
【问题描述】:

我用 C 语言编写了一个代码,它基本上列出了一个巨大数字的所有质因数,它使用 gmp 库存储。这里是:

int is_div(mpz_t number, mpz_t i) {
    return mpz_divisible_p(number,i)!=0;
}

mpz_t * prime_divs(mpz_t number){
    mpz_t * prime_dividers = NULL;
    mpz_t i, i_squared,TWO, comp;
    mpz_inits(i, i_squared, TWO, comp, NULL);
    mpz_set_ui(i,2);
    mpz_mul(i_squared, i ,TWO);
    while(mpz_cmp(i_squared,number)<=0){
        if(is_div(number,i)){
            mpz_fdiv_q(comp, number, i);
            if(is_prime(i)) append(&prime_dividers,i);
            if(is_prime(comp)) append(&prime_dividers,comp);
        }
        mpz_add_ui(i,i,1);
        mpz_mul(i_squared, i ,i);
    }
    mpz_clears(i, i_squared, TWO, comp, NULL);
    return prime_dividers;
}

请注意,这里没有定义函数int is_prime(mpz_t n),因为它很长。只要知道它是米勒拉宾素性检验的确定性变体(最多 3,317,044,064,679,887,385,961,981)的实现。函数void append(mpz_t** arr, mpz_t i) 也是如此,它只是一个将其附加到列表的函数。

所以我的prime_divs 函数在[2,sqrt(number)] 范围内搜索除number 的所有整数i。如果是这种情况,它然后计算它的互补除数(即number/i)并确定它们中的任何一个是否是素数。如果这些整数是素数,那么它们将使用append 附加到一个列表中。

有什么方法可以让prime_divs 更快?

【问题讨论】:

  • Erathosthenes 的筛子比确定性的 Miller-Rabin 对大量数字慢得多。
  • 但是测试[2, sqrt(number)] 范围内的每个数字可能会否定使用 M-R 获得的任何效率。您至少应该将循环限制为奇数,因为唯一的偶数是2
  • GMP 源 tarball 在 demos 目录中包含一个程序 factorize.c,它实现了 Pollard's rho algorithm。这不是已知的用于分解大整数的最快算法,但它比新算法更容易理解。
  • 您可以通过在每次循环中将 2 添加到 i 来立即将速度加倍(在首先检查 2 和 3 之后)。这样你只测试奇数除数。您可以使用更复杂的模式来剔除更多因素(例如,一旦超过 3,只测试 1 或 5 mod 6 的除数)。图案越大,您必须走得越远才能应用它。
  • @Michael 你的反对毫无意义。对于 348,它是这样的:首先找到因子 2,它出现了两次。所以你除以 4 得到 87。然后你继续寻找,你找到了 3,它出现了一次。所以你除以 3 得到 29。然后你继续查找 sqrt(29),但找不到其他因素。这意味着 29 必须是素数,所以你完成了:348 = 2*2*3*29。这是非常非常简单的。你错过了29这个因素吗?不,当然不。这是检查所有可能因素后剩下的素数。

标签: c primes prime-factoring factoring


【解决方案1】:

我怀疑您可以通过首先检查小的除数来节省时间。使用埃拉托色尼筛法建立一个低于 5,000 或 10,000 的素数列表。然后使用该列表查找大数字中的小因素(如果有的话)。每次你找到一个因子(可能多次找到同一个因子)时,将那个因子除以减少目标数字的大小。

当您用尽小素数列表时,可能值得在尝试分解大残差之前对其进行快速素性检查。这避免了浪费大量时间寻找大素数的因子。您需要测试这个想法,看看它是否真的为您节省了时间。

只有这样你才能调用 M-R 检验来找出剩余的因素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 2017-02-15
    • 2016-03-17
    • 2023-01-13
    • 1970-01-01
    • 2013-04-11
    相关资源
    最近更新 更多