浅浅谈效率的持续改进
效率,一直是多有程序员追逐的目标,每个人在实践的过程中都发现了很多提高效率的办法,从程序结构的改进到对CPU指令集的研究。各种奇技淫巧都不惜一用。
但通常的情况下,效率是在不牺牲代码可读性和稳定性的基础上提高的,除非有很变态的要求。
我个人在实践中也经常尝试提高程序效率,下面只说说自己的一点拙见
举个例子,求前5000个素数
素数,就是只能被1和它自身整除的数。通过这个定义,很容易写出一个直观的算法
2 void gcd(int num)
3 {
4 int j;
5 bool prime = true;
6 for(int i = 0, k = 2; i < num; k ++)
7 {
8 for(j = 2; j <= k; j ++)
9 {
10 if(k%j==0)
11 {
12 prime = false;
13 break;
14
15 }
16 }
17 if(prime)
18 {
19 // cout << i << ":" << k << endl;
20 i ++;
21 }
22 else
23 {
24 prime = true;
25 }
26 }
27 }
但是,当一个数是素数时,它必须尝试这整除2~N所有的整数,但实际上,只需要整除到它的平方根就可以确定其是否是素数了。
2 void gcd(int num)
3 {
4 int j;
5 bool b = true;
6 for(int i = 0, k = 2; i < num; k ++)
7 {
8 for(j = 2; j <= int(sqrt(double(k))); j ++)
9 {
10 if(k%j==0)
11 {
12 b = false;
13 break;
14
15 }
16 }
17 if(b)
18 {
19 // cout << i << ":" << k << endl;
20 i ++;
21 }
22 else
23 {
24 b = true;
25 }
26 }
27 }
现在,效率有了显著提高。
但还有一点小小的问题,
这里,每次循环都要重新计算k的平方根。当日,编译器也许会帮你优化掉这个地方,用一个临时变量代替sqrt(k),但有一条原则是永远不要指望编译器帮你优化,毕竟不是每个编译器都会做这样的工作的。所以,我们应该自己做,至少这里很明显的,我们可以自己优化
for(j = 2; j <= m; j ++)
经过三次改进之后,程序的效率有了明显提高。
这里只是举了个例子,并不想深入研究素数算法。也就是说,现有的逻辑和算法通常是存在这改进空间的。
再举个例子,三维数组
我们知道std::vector是允许拷贝的,也就是说vector<vector<vector<T> > >这个定义是合法的,虽然显得有点难看。
但是,你知道它潜在的效率隐患吗?
如果数组的大小是固定的,在整个运行过程中不会被改变,那么我们初始化一次也就行了。并没什么大的影响
但当最外层的vector需要增长的时候,问题就大了。想想,第二层的vector需要复制到新的存储区,而第二层中每个vector本身有是个vector的集合,也就是当最外层增长时,需要做M*N*P次拷贝。
解决方法就是一定不要用这种嵌套的vector。可以模拟三维数组,比如散列表,用struct{x,y,z}做键。
以上这些,都是不需要什么数学知识就可以做到的。关键在于认真分析和发现。
就说这么多吧,希望多交流