在C中找到大整数的所有质因子的更好方法?

Posted

技术标签:

【中文标题】在C中找到大整数的所有质因子的更好方法?【英文标题】:Better way to find all the prime factors of huge integers in 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这个因素吗?不,当然不。这是检查所有可能因素后剩下的素数。 【参考方案1】:

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

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

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

【讨论】:

以上是关于在C中找到大整数的所有质因子的更好方法?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法找到给定整数的质因子数?

输入一个正整数,按照从小到大的顺序输出它的所有质因子(如180的质因子为2 2 3 3 5 )

C语言经典习题

401Python 求合数的所有质数因子

最大质因子序列

Uva1635 二项式递推+质因子分解+整数因子分解