这是我的代码,但我想优化它。我不喜欢它在n的平方根之前测试所有数字的想法,考虑到一个人可能面临找到因素的事实大量的。你的答案会有很大的帮助。提前谢谢。
unsigned int* factor(unsigned int n)
{
unsigned int tab[40];
int dim=0;
for(int i=2;i<=(int)sqrt(n);++i)
{
while(n%i==0)
{
tab[dim++]=i;
n/=i;
}
}
if(n>1)
tab[dim++]=n;
return tab;
}
答案 0 :(得分:5)
以下是关于如何在“正确的”c ++中执行此操作的建议(因为您标记为c++)。
PS。几乎忘了提及:我优化了对sqrt
的调用:)
在http://liveworkspace.org/code/6e2fcc2f7956fafbf637b54be2db014a
上查看#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
typedef unsigned int uint;
std::vector<uint> factor(uint n)
{
std::vector<uint> tab;
int dim=0;
for(unsigned long i=2;i*i <= n; ++i)
{
while(n%i==0)
{
tab.push_back(i);
n/=i;
}
}
if(n>1)
tab.push_back(n);
return tab;
}
void test(uint x)
{
auto v = factor(x);
std::cout << x << ":\t";
std::copy(v.begin(), v.end(), std::ostream_iterator<uint>(std::cout, ";"));
std::cout << std::endl;
}
int main(int argc, const char *argv[])
{
test(1);
test(2);
test(4);
test(43);
test(47);
test(9997);
}
输出
1:
2: 2;
4: 2;2;
43: 43;
47: 47;
9997: 13;769;
答案 1 :(得分:3)
如果您使用
... i*i <= n; ...
它的运行速度可能比i&lt; = sqrt(n)
快得多顺便说一下,你应该尝试处理负数n的因素,或者至少确保你永远不会传递一个负数
答案 2 :(得分:3)
有一个简单的改变可以减少运行时间:将所有的2分解出来,然后只检查奇数。
答案 3 :(得分:1)
我怕你不能。地球上没有已知的方法可以在多项式时间内对大整数进行分解。但是,有一些方法可以帮助您略微(不显着)加速您的程序。搜索维基百科以获取更多参考。 http://en.wikipedia.org/wiki/Integer_factorization
答案 4 :(得分:1)
从你的解决方案中可以看出,你发现基本上所有的素数(条件while (n%i == 0)
)都是这样的,特别是对于大数字的情况,你可以预先计算素数,并且只检查那些素数。质数计算可以使用Sieve of Eratosthenes方法或其他一些有效的方法来完成。
答案 5 :(得分:1)
unsigned int* factor(unsigned int n)
如果unsigned int
是典型的32位类型,则数字太小,无法获得任何更高级的算法。试验部门的通常增强当然是值得的。
如果您将除法移出循环2,并且仅在循环中除以奇数,如mentioned by 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
,<= 100000
还是<= 1000000
需要测试,我的肠道感觉说一个较小的值会平均更好)。如果在试验分割阶段之后,因子分解尚未完成,请使用例如,检查剩余因子是否为素数。 Miller-Rabin检验的确定性(对于所讨论的范围)变体。如果不是,请使用您最喜欢的高级算法搜索因子。对于64位数字,我建议Pollard's rho algorithm或椭圆曲线分解。 Pollard的rho算法更容易实现,并且这个数量的数字在相当的时间内找到因子,所以这是我的第一个建议。
答案 6 :(得分:0)
Int是小到遇到任何性能问题的方法。我只是尝试使用boost来测量算法的时间,但是无法获得任何有用的输出(太快)。所以你根本不用担心整数。
如果你使用i * i,我能够在15.097秒内计算出1.000.000个9位整数。优化算法是好的,但不是“浪费”时间(取决于你的情况),重要的是要考虑一个小的改进是否值得付出努力。有时候你必须问自己,你是否需要能够在10秒钟内计算出1.000.000英镑或者15英镑就可以了。