编程时算法很重要,是要努力学习的,虽然很难学,但必须去学,
程序的优化,从代码效率或者cpu效率着手,虽然很重要,效果有时也很明显,但这些在算法优化面前就显得太弱小了,比如这个求素数个数问题,试除法与筛法比较无论如何优化也难以望其相背,即使时筛法,在更好的算法面前速度也是太慢了,完全不在一个数量级上。以下给出一段代码,应用两种不同的算法,可以看到两种算法在速度上有着巨大的差别,运行好的算法,可以有飞一样的感觉,来感受一下吧。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include<math.h>
#include <time.h>
#define LINT long long
int main01(int n )
{
unsigned char *BITArray;
long maxsize;
long i, j;
int sqn,k;
if(n==2)return
1;
if(n<2)return 0;
k=1;
maxsize = n / CHAR_BIT+(n%CHAR_BIT!=0);
BITArray = ( unsigned char * )malloc( maxsize * sizeof( unsigned char ) );
assert( NULL != BITArray );
for( i = 0;i< maxsize; ++i )
BITArray[ i ] = 0xff;
sqn=(int)(sqrt(n)+0.001);
for( i = 3; i<=sqn; i+=2)
if( BITArray[ (i -3)/ CHAR_BIT ] & ( 1 << (i -3)% CHAR_BIT ) )
{
++k;
for( j = i*i; j<=n;j+=i*2)
BITArray[( j -3)/ CHAR_BIT ] &= ~( 1 << (( j -3) % CHAR_BIT ) );
}
for( ;i<=n ;i+=2)
if( BITArray[ (i -3)/ CHAR_BIT ] & ( 1 <<( i-3) % CHAR_BIT ) )
++k;
free(BITArray);
return k;
}
int main( )
{
int m,n;
int main01( int);
int main02( int);
LINT primesum(LINT N);
long t;
printf("main01:\n");
t=clock();
n=300000000;
m=main01(n);
printf("n= %d time:%ld
sum:%d\n",n,clock()-t,m);
printf("main02:\n");
t=clock();
n=300000000;
m=main02( n);
printf("n= %d time:%ld
sum:%d\n",n,clock()-t,m);
printf("primesum:\n");
t=clock();
n=300000000;
m=primesum(n) ;
printf("n= %d time:%ld
sum:%d\n",n,clock()-t,m);
t=clock();
n=2000000000;
m=primesum(n) ;
printf("n= %d time:%ld
sum:%d\n",n,clock()-t,m);
return 0;
}
int main02( int n)
{
unsigned int*BITArray;
int maxsize,i,j,k;
int temp,sqn;
if(n==2)return
1;
if(n<2)return 0;
k=1;
maxsize =n/ 64+((n%64)!=0);
BITArray = ( unsigned int* )malloc( maxsize * sizeof( unsigned int) );
memset(BITArray,0,maxsize*sizeof(unsigned int));
assert( NULL != BITArray );
sqn=(int)(sqrt(n)+0.5);
for( i = 3;i<=sqn;i+=2)
{
temp=(i-3)/2;
if( (BITArray[temp/32] & ( 1u << (temp%32)))==0 )
{
++k;
for( j=i*i;j<=n;j+=i*2)
{
temp=(j-3)/2;
BITArray[temp/32]|=(1u<<(temp%32));
}
}
}
for(;i<=n; i+=2)
{
temp=(i-3)/2;
if( (BITArray[temp/32] & ( 1u << (temp%32)))==0 )
++k;
}
free(BITArray);
return k;
}
inline LINT V2IDX(LINT v, LINT N, LINT Ndr, LINT nv) {
return v >= Ndr ? (N/v - 1) : (nv - v);
}
LINT primesum(LINT N) {
LINT *S;
LINT *V;
LINT sum;
LINT r = (LINT)sqrt(N);
LINT Ndr = N/r;
assert(r*r <= N and (r+1)*(r+1) > N);
LINT nv = r + Ndr - 1;
V = new LINT[nv];
S = new LINT[nv];
for (LINT i=0; i<r; i++) {
V[i] = N/(i+1);
}
for (LINT i=r; i<nv; i++) {
V[i] = V[i-1] - 1;
}
for (LINT i=0; i<nv; i++) {
S[i] = V[i]- 1;
}
for (LINT p=2; p<=r; p++) {
if (S[nv-p] > S[nv-p+1]) {
LINT sp = S[nv-p+1];
LINT p2 = p*p;
for (LINT i=0; i<nv; i++) {
if (V[i] >= p2) {
S[i] -= (S[V2IDX(V[i]/p, N, Ndr, nv)] - sp);
} else {
break;
}
}
}
}
sum=S[0];
delete(S);
delete(V);
return sum;
}
下面是以上代码在某在线编程网站运行的结果。
main01:
n= 300000000 time:1640964
sum:16252325
main02:
n= 300000000 time:1532777
sum:16252325
primesum:
n= 300000000 time:11829
sum:16252325
n= 2000000000 time:45016
sum:98222287