unsigned int* factor(unsigned int n)
如果unsigned int
是典型的 32 位类型,则数字太小,任何更高级的算法都无法获得回报。试炼师平时的强化当然是值得的。
如果您将除以 2 移出循环,并且只除以循环中的奇数,如Pete Becker 所述,您实际上是将输入数字分解所需的除法数减半,从而加快该函数几乎是 2 倍。
如果您更进一步,并从循环中的除数中消除 3 的倍数,您可以减少除数,从而将速度提高接近 3 倍(平均而言;大多数数字没有任何大质因数,但可以被 2 或 3 整除,对于那些加速比要小得多;但无论如何这些数字很快就会被分解。如果你分解更大范围的数字,大部分时间都花在分解少数数字上有大的素数除数)。
// if your compiler doesn't transform that to bit-operations, do it yourself
while(n % 2 == 0) {
tab[dim++] = 2;
n /= 2;
}
while(n % 3 == 0) {
tab[dim++] = 3;
n /= 3;
}
for(int d = 5, s = 2; d*d <= n; d += s, s = 6-s) {
while(n % d == 0) {
tab[dim++] = d;
n /= d;
}
}
如果您真的经常调用该函数,那么值得预先计算不超过 65535 的 6542 个素数,将它们存储在静态数组中,然后仅除以素数以消除所有先验保证不会找到除数的除法.
如果unsigned int
恰好大于 32 位,那么使用更高级的算法之一将是有利可图的。您仍然应该从试验除法开始,以找到小的主要因素(无论小应该意味着<= 1000
,还是可能需要测试,我的直觉是平均而言,较小的值之一会更好)<= 10000
。如果在试除法阶段之后因式分解尚未完成,则使用例如 Miller-Rabin 测试的确定性(针对所讨论的范围)变体检查剩余因子是否为素数。如果不是,请使用您最喜欢的高级算法搜索一个因子。对于 64 位数字,我推荐Pollard 的 rho 算法<= 100000
<= 1000000
或椭圆曲线分解。Pollard 的 rho 算法更容易实现,并且对于这么大的数字可以在可比较的时间内找到因子,所以这是我的第一个建议。