找回密码
 欢迎注册
楼主: shingyuan

[求助] 求因子个数的问题

[复制链接]
发表于 2011-11-9 21:20:43 | 显示全部楼层
在吃晚饭的时候,回顾了一遍我写的代码,发现一个大bug,待会儿给出修改后的代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-11-9 21:56:29 | 显示全部楼层
下面是修正后的代码,速度基本和3楼同
  1. // URL: http://bbs.emath.ac.cn/redirect.php?tid=3786&goto=lastpost#lastpost
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <math.h>

  6. typedef unsigned long DWORD;
  7. typedef unsigned char BYTE;


  8. // 一定范围内质数的个数
  9. //                           10                            4
  10. //                          100                           25
  11. //                        1,000                          168
  12. //                       10,000                        1,229
  13. //                      100,000                        9,592
  14. //                    1,000,000                       78,498
  15. //                   10,000,000                      664,579
  16. //                  100,000,000                    5,761,455
  17. //                1,000,000,000                   50,847,534
  18. //               10,000,000,000                  455,052,511
  19. //              100,000,000,000                4,118,054,813
  20. //            1,000,000,000,000               37,607,912,018
  21. //           10,000,000,000,000              346,065,536,839
  22. //          100,000,000,000,000            3,204,941,750,802
  23. //        1,000,000,000,000,000           29,844,570,422,669
  24. //       10,000,000,000,000,000          279,238,341,033,925
  25. //      100,000,000,000,000,000        2,623,557,157,654,233
  26. //    1,000,000,000,000,000,000       24,739,954,287,740,860
  27. //  估计x 范围内的质数的个数, 欧拉公式 pi(x)=x /( ln(x));

  28. // 经过测试,
  29. // 在1-1百万之间,相邻2个质数的最大差为114,这两个质数分别为492113,492227
  30. // 在1-1千万之间,相邻2个质数的最大差为154,这两个质数分别为4652353,4652507
  31. // 在1-3千万之间,相邻2个质数的最大差为210,这两个质数分别为20831323,20831533
  32. // 在1-1亿之间,  相邻2个质数的最大差为220,这两个质数分别为47326693,47326913


  33. static LARGE_INTEGER freq;

  34. static BOOL initFreq()
  35. {
  36.         BOOL ret;
  37.         if ( !QueryPerformanceFrequency( &freq) )
  38.         {        ret=FALSE;        }
  39.         else
  40.         {        ret=TRUE;        }
  41.         return ret;
  42. }

  43. double currTime() //使用高精度计时器
  44. {       
  45.         LARGE_INTEGER performanceCount;
  46.         BOOL result;
  47.         double time=0.0;
  48.         BOOL bRet=TRUE;

  49.         if (freq.QuadPart==0)
  50.         {
  51.                 bRet=initFreq();
  52.         }
  53.        
  54.         if (bRet)
  55.         {
  56.                 result=QueryPerformanceCounter(  &performanceCount );
  57.                 time= performanceCount.HighPart * 4294967296.0 + performanceCount.LowPart;
  58.                 time=time / (   freq.HighPart * 4294967296.0 + freq.LowPart);
  59.         }
  60.         return time;
  61. }

  62. #define MAX_PRIME 302

  63. struct FAC_ARR_ST
  64. {
  65.         int fc;
  66.         struct
  67.         {
  68.                 DWORD p;
  69.                 int   e;
  70.         }arr[10]; //2^32以内的数最大9个素因子
  71. };


  72. struct FAC_ARR_ST g_facTab;

  73. void add_to_facTab(DWORD p)
  74. {
  75.         int i;
  76.         int bfind=0;
  77.         for (i=0;i<g_facTab.fc;i++)
  78.         {
  79.                 if ( g_facTab.arr[ i ].p==p)
  80.                 {
  81.                         g_facTab.arr[ i ].e++;
  82.                         bfind=1;
  83.                         break;
  84.                 }
  85.         }

  86.         if ( !bfind )
  87.         {
  88.                 g_facTab.arr[g_facTab.fc].p=p;
  89.                 g_facTab.arr[g_facTab.fc].e=1;
  90.                 g_facTab.fc++;
  91.         }
  92. }

  93. //**********************************************
  94. // n 不能大于L2 cache,否则效能很低
  95. DWORD Sift32(DWORD n,DWORD *primeTab)
  96. // 对0到n 之间(不包括n)的数进行筛选,返回质数的个数
  97. //**********************************************
  98. {
  99.         BYTE *pBuff= new BYTE[n];
  100.         if (pBuff==NULL)
  101.                 return 0;

  102.         DWORD i,sqrt_n,p;
  103.         DWORD pn;
  104.         //----------------------------
  105.         sqrt_n=(DWORD)(sqrt((double)n)+1);

  106.         while (sqrt_n * sqrt_n >=n)
  107.                 sqrt_n--;

  108.         memset(pBuff,1,n*sizeof(BYTE));
  109.         *pBuff=0;
  110.         *(pBuff+1)=0; //1不是质数
  111.         *(pBuff+2)=1; //2是质数

  112.         for ( i=4;i<n;i+=2) //筛去2的倍数,不包括2
  113.                 *(pBuff+i)=0;

  114.         for (i=3;i<=sqrt_n;) //i 是质数
  115.         {
  116.                 for (p=i*i;p<n; p+=2*i)
  117.                         *(pBuff+p)=0; //筛去i 的奇数倍
  118.                 i+=2;
  119.                 while ( *(pBuff+i)==0 )
  120.                         i++; //前进到下一个质数
  121.         }
  122.         pn=0; //素数个数

  123.         if ( primeTab==NULL)
  124.         {
  125.                 for (i=2;i<n;i++)
  126.                 {
  127.                         if (pBuff[ i ])
  128.                                 pn++;
  129.                 }
  130.         }
  131.         else
  132.         {
  133.                 for (i=2;i<n;i++)
  134.                 {
  135.                         if (pBuff[ i ])
  136.                                 primeTab[pn++]=i;
  137.                 }
  138.         }
  139.         delete[] pBuff;
  140.         return pn;
  141. }


  142. void check_all(DWORD max_n)
  143. {
  144.         DWORD *primeTab=NULL;
  145.         DWORD primeCount;
  146.         DWORD i,j,k;
  147.         int f_c;     //因子数
  148.         int max_fc;  //最大因子数

  149.         //创建一个素数表
  150.         primeCount=Sift32(MAX_PRIME,NULL);  //得到MAX_PRIME以内的素数个数
  151.         primeTab=(DWORD *)malloc(sizeof(DWORD)* (primeCount+1));
  152.         Sift32(MAX_PRIME,primeTab);
  153.         primeTab[primeCount]=2147483647; //设置一个栅栏

  154.        
  155.         for (max_fc=0,i=2;i<=max_n;i++)
  156.         {
  157.                 DWORD na[2];
  158.                 if (i & 1) //i是奇数
  159.                 {    na[0]=i; na[1]=(i+1)/2;}
  160.                 else
  161.                 {     na[0]=i/2; na[1]=i+1;  }
  162.                
  163.                 for (g_facTab.fc=0,j=0;j<2;j++)
  164.                 {
  165.                         DWORD n,r;
  166.                        
  167.                         r=n=na[j];
  168.                         // primeTab[primeCount]=2147483647,保证循环能够终止
  169.                        
  170.                         for (k=0; primeTab[k] * primeTab[k] <= n ; )
  171.                         {
  172.                                 DWORD prime=primeTab[k];
  173.                                 if ( r % prime==0)
  174.                                 {
  175.                                         while ( r % prime==0)
  176.                                         {
  177.                                                 add_to_facTab(prime);  //增加素因子到素因子表 g_facTab
  178.                                                 r/=prime;
  179.                                         }
  180.                                 }
  181.                                 k++;
  182.                                 if ( primeTab[k] > r)
  183.                                         break;
  184.                         }

  185.                         if (r >1)
  186.                                 add_to_facTab(r);  //增加素因子到素因子表 g_facTab
  187.                 }

  188.                 for (f_c=1,j=0;j<g_facTab.fc;j++)
  189.                         f_c *= (g_facTab.arr[j].e +1);

  190.                 //printf("%u*(%u+1)/2 with %u factor\n",i,i,f_c);
  191.                 if (f_c >max_fc)
  192.                 {
  193.                         printf("%u*(%u+1)/2 with %u factor\n",i,i,f_c);
  194.                         max_fc=f_c;
  195.                 }
  196.         }
  197.         free(primeTab);
  198. }

  199. int main(int argc, char* argv[])
  200. {
  201.         double t=currTime();
  202.         //check_all(92681);
  203.         check_all(65535);
  204.         t=currTime()-t;
  205.         printf("it take %.6f ms\n",t*1000);
  206.         return 0;
  207. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-11-12 22:14:59 | 显示全部楼层
版主的代码需要的时间啃下哟,学习中
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-11-29 23:07:36 | 显示全部楼层
非常感谢各位朋友的帮助,这些代码需要好好消化学习
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-29 02:07 , Processed in 0.044488 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表