liangbch
发表于 2008-12-1 12:44:42
55楼代码虽然有bug,但依然有正确的思想,我用其思想,改进了程序,速度提高1倍多,在计算10^8以内的smith素数时,用时从23秒提高到11秒。
55楼代码中,“j *= p;" 这句话隐藏了一个较难发现的bug. 如果 j<=end 且j*p>end. 但执行了j*=p后,j仍然有可能小于end,
例如:
j=3251*3251= 10569001;
j*=p 后,本应该是34359822251, 但由于整数溢出,j的值变为83883.
liangbch
发表于 2008-12-1 12:49:35
下面的代码段 筛出 base 到end之间所有smith数
g_valueArray的初值为 base+i;
g_digSumArray [ i ]的初值为 0;i=0;
while (primeTab*primeTab<=end && i<primeCount)
{
DWORD k,m,np;
DWORD npx;
DWORD npx_end;
BYTE dsum;
np=primeTab;
dsum=getDigSum2(np);
k= (base + np-1)/np;
if (k<np)
k=np;
m= k*np;
while (m <=end)
{
g_valueArray /= np;
g_digSumArray += dsum;
m+= np;
}
npx=np;
npx_end=end/npx;
while (npx<=npx_end)
{
npx *= np;
m= (base + npx-1)/npx*npx;
while (m <=end)
{
g_valueArray /= np;
g_digSumArray += dsum;
m+= npx;
}
}
i++;
}
liangbch
发表于 2008-12-1 12:54:18
为了便于阅读,将输出 base到end之间的smith数的代码一并贴出for (i=0;i<SIFT_BLOCK_LEN && i+base<=n;i++)
{
DWORD x=i+base;
WORD s1= getDigSum2(x);
WORD s2= g_digSumArray;
if (s1==0)
continue;
if ( g_valueArray !=1 && g_valueArray != x)
s2+=getDigSum2(g_valueArray);
if (s1==s2)
{
if (fp!=NULL)
{
numBuff=x;
if ( countInBuff*sizeof(DWORD)>=sizeof(numBuff) )
{
fwrite(numBuff,sizeof(DWORD),countInBuff,fp);
countInBuff=0;
}
}
count++;
}
}
suan1024
发表于 2008-12-1 17:38:48
大哥厉害啊!学习了!