LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: chai2010

[原创]浅析求素数算法

[复制链接]
 楼主| 发表于 2006-11-6 09:41:29 | 显示全部楼层
32位无符号乘法,返回高32位。
低32位可以直接(u*v)得到


  1. unsigned mulhu(unsigned u, unsigned v)
  2. {
  3.    unsigned u0, v0, w0;
  4.    unsigned u1, v1, w1, w2, t;

  5.    u0 = u & 0xFFFF;  u1 = u >> 16;
  6.    v0 = v & 0xFFFF;  v1 = v >> 16;
  7.    w0 = u0*v0;
  8.    t  = u1*v0 + (w0 >> 16);
  9.    w1 = t & 0xFFFF;
  10.    w2 = t >> 16;
  11.    w1 = u0*v1 + w1;

  12.    return u1*v1 + w2 + (w1 >> 16);
  13. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-6 11:40:06 | 显示全部楼层
(x*y)%m代码修改如下



  1. // 计算(u*v)%m

  2. unsigned mul_mod(unsigned u, unsigned v, unsigned z)
  3. {
  4.         // 如果u*v没有溢出, 则直接计算

  5.         if(u*v >= 1.0*u*v) return (u*v)%z;

  6.         // 进行长乘法(结果为64位)

  7.         unsigned u0, v0, w0;
  8.         unsigned u1, v1, w1, w2, t;

  9.         u0 = u & 0xFFFF;  u1 = u >> 16;
  10.         v0 = v & 0xFFFF;  v1 = v >> 16;
  11.         w0 = u0*v0;
  12.         t  = u1*v0 + (w0 >> 16);
  13.         w1 = t & 0xFFFF;
  14.         w2 = t >> 16;
  15.         w1 = u0*v1 + w1;

  16.         // x为高32位, y为低32位

  17.         unsigned x = u1*v1 + w2 + (w1 >> 16);
  18.         unsigned y = u*v;

  19.         // 进行长除法(除数为64位)

  20.         for (int i = 1; i <= 32; i++)
  21.         {
  22.                 t = (int)x >> 31;                // All 1's if x(31) = 1.

  23.                 x = (x << 1) | (y >> 31);        // Shift x || y left
  24.                 y <<= 1;                        // one bit.
  25.                
  26.                 if((x|t) >= z) { x -= z; y++; }
  27.         }

  28.         return x;        // y为商, x为余数
  29. }

  30. // 判断是否是费马(伪)素数

  31. static bool isFermatNum(unsigned p)
  32. {
  33.         unsigned m = p--;
  34.         unsigned r = 2%m;
  35.         unsigned k = 1;
  36.    
  37.         // 蒙格马利快速幂模算法

  38.         while(p > 1)
  39.         {
  40.                 if(p&1) k = mul_mod(k, r, m);
  41.                 r = mul_mod(r, r, m); p >>= 1;
  42.         }

  43.         return mul_mod(k, r, m) == 1;
  44. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-6 12:23:45 | 显示全部楼层
整理之后


  1. // 函数: bool isPrime(unsigned n);
  2. // 描述: 判断n(0, 2^32-1)是否为素数
  3. // 算法: 费马小定理-卡尔麦克数
  4. // 作者: 柴树杉
  5. // 时间: 2006-11-06
  6. // 主页: [url]chaishushan.googlepages.com[/url]

  7. #include <assert.h>
  8. #include <stdlib.h>

  9. // 计算数组的元素个数

  10. #define NELEMS(x) ((sizeof(x)) / (sizeof((x)[0])))

  11. // 2^32范围内的所有卡尔麦克数

  12. static const unsigned CarmichaeNumbers[] =
  13. {
  14. 561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,62745,
  15. 63973,75361,101101,115921,126217,162401,172081,188461,252601,278545,294409,
  16. 314821,334153,340561,399001,410041,449065,488881,512461,530881,552721,656601,
  17. 658801,670033,748657,825265,838201,852841,997633,1024651,1033669,1050985,
  18. 1082809,1152271,1193221,1461241,1569457,1615681,1773289,1857241,1909001,
  19. 2100901,2113921,2433601,2455921,2508013,2531845,2628073,2704801,3057601,
  20. 3146221,3224065,3581761,3664585,3828001,4335241,4463641,4767841,4903921,
  21. 4909177,5031181,5049001,5148001,5310721,5444489,5481451,5632705,5968873,
  22. 6049681,6054985,6189121,6313681,6733693,6840001,6868261,7207201,7519441,
  23. 7995169,8134561,8341201,8355841,8719309,8719921,8830801,8927101,9439201,
  24. 9494101,9582145,9585541,9613297,9890881,10024561,10267951,10402561,10606681,
  25. 10837321,10877581,11119105,11205601,11921001,11972017,12261061,12262321,
  26. 12490201,12945745,13187665,13696033,13992265,14469841,14676481,14913991,
  27. 15247621,15403285,15829633,15888313,16046641,16778881,17098369,17236801,
  28. 17316001,17586361,17812081,18162001,18307381,18900973,19384289,19683001,
  29. 20964961,21584305,22665505,23382529,25603201,26280073,26474581,26719701,
  30. 26921089,26932081,27062101,27336673,27402481,28787185,29020321,29111881,
  31. 31146661,31405501,31692805,32914441,33302401,33596641,34196401,34657141,
  32. 34901461,35571601,35703361,36121345,36765901,37167361,37280881,37354465,
  33. 37964809,38151361,38624041,38637361,39353665,40160737,40280065,40430401,
  34. 40622401,40917241,41298985,41341321,41471521,42490801,43286881,43331401,
  35. 43584481,43620409,44238481,45318561,45877861,45890209,46483633,47006785,
  36. 48321001,48628801,49333201,50201089,53245921,53711113,54767881,55462177,
  37. 56052361,58489201,60112885,60957361,62756641,64377991,64774081,65037817,
  38. 65241793,67371265,67653433,67902031,67994641,68154001,69331969,70561921,
  39. 72108421,72286501,74165065,75151441,75681541,75765313,76595761,77826001,
  40. 78091201,78120001,79411201,79624621,80282161,80927821,81638401,81926461,
  41. 82929001,83099521,83966401,84311569,84350561,84417985,87318001,88689601,
  42. 90698401,92625121,93030145,93614521,93869665,94536001,96895441,99036001,
  43. 99830641,99861985,100427041,101649241,101957401,102090781,104404861,104569501,
  44. 104852881,105117481,105309289,105869401,106041937,107714881,109393201,109577161,
  45. 111291181,114910489,115039081,115542505,116682721,118901521,119327041,120981601,
  46. 121247281,122785741,124630273,127664461,128697361,129255841,129762001,130032865,
  47. 130497361,132511681,133205761,133344793,133800661,134809921,134857801,135556345,
  48. 136625941,139592101,139952671,140241361,144218341,145124785,146843929,150846961,
  49. 151530401,151813201,153589801,153927961,157731841,158404141,158864833,159492061,
  50. 161035057,161242705,161913961,163954561,167979421,168659569,169057801,169570801,
  51. 170947105,171454321,171679561,172290241,172430401,172947529,173085121,174352641,
  52. 175997185,176659201,178451857,178482151,178837201,180115489,181154701,182356993,
  53. 184353001,186393481,186782401,187188001,188516329,188689501,189941761,193708801,
  54. 193910977,194120389,194675041,196358977,200753281,206955841,208969201,212027401,
  55. 213835861,214850881,214852609,216821881,221884001,225745345,226509361,227752993,
  56. 228842209,230630401,230996949,231194965,237597361,238244041,238527745,241242001,
  57. 242641153,246446929,247095361,250200721,252141121,255160621,256828321,257495641,
  58. 258634741,266003101,270857521,271481329,271794601,273769921,274569601,275283401,
  59. 277241401,278152381,279377281,280067761,280761481,288120421,289766701,289860481,
  60. 291848401,292244833,292776121,295643089,295826581,296559361,299736181,300614161,
  61. 301704985,302751505,306871201,311388337,318266641,321197185,321602401,325546585,
  62. 328573477,329769721,333065305,333229141,334783585,338740417,346808881,348612265,
  63. 354938221,357277921,357380101,358940737,360067201,362569201,364590721,366532321,
  64. 366652201,367804801,367939585,368113411,382304161,382536001,390489121,392099401,
  65. 393122521,393513121,393716701,395044651,395136505,396262945,399906001,403043257,
  66. 403317421,405739681,413058601,413138881,413631505,416964241,417241045,419520241,
  67. 426821473,429553345,434330401,434932961,438359041,440306461,440707345,455106601,
  68. 458368201,461502097,461854261,462199681,471441001,471905281,473847121,477726145,
  69. 481239361,483006889,484662529,490099681,490503601,492559141,496050841,499310197,
  70. 503758801,507726901,509033161,510825601,511338241,516684961,517937581,518117041,
  71. 518706721,527761081,529782121,530443201,532758241,533860309,540066241,542497201,
  72. 544101481,545363281,545570641,547652161,548871961,549117205,549333121,549538081,
  73. 551672221,552894301,555465601,556199281,556450777,557160241,557795161,558570961,
  74. 558977761,561481921,561777121,564651361,568227241,569332177,573896881,577240273,
  75. 579606301,580565233,590754385,593234929,595405201,597717121,600892993,602074585,
  76. 602426161,602593441,606057985,609865201,611397865,612347905,612816751,616463809,
  77. 618068881,620169409,621101185,625060801,625482001,629692801,631071001,633639097,
  78. 638959321,642708001,652969351,656187001,662086041,672389641,683032801,683379841,
  79. 684106401,686059921,689880801,697906561,698548201,702683101,703995733,704934361,
  80. 705101761,707926801,710382401,710541481,711374401,713588401,717164449,721244161,
  81. 722923201,727083001,739444021,743404663,744866305,745864945,746706961,752102401,
  82. 759472561,765245881,771043201,775368901,775866001,776176261,781347841,784966297,
  83. 790020001,790623289,794937601,798770161,804978721,809702401,809883361,814056001,
  84. 822531841,824389441,824405041,829678141,832060801,833608321,834244501,834720601,
  85. 836515681,839275921,841340521,842202361,843704401,847491361,849064321,851703301,
  86. 851934601,852729121,854197345,855734401,860056705,863984881,867800701,868234081,
  87. 876850801,882796321,885336481,888700681,891706861,897880321,902645857,914801665,
  88. 918661501,928482241,930745621,931694401,934784929,935794081,939947009,940123801,
  89. 941056273,945959365,947993761,954732853,955134181,957044881,958735681,958762729,
  90. 958970545,962442001,962500561,963163201,963168193,968553181,968915521,975303121,
  91. 977737321,977892241,981567505,981789337,985052881,986088961,990893569,993420289,
  92. 993905641,1001152801,1018928485,1027334881,1030401901,1031750401,1035608041,
  93. 1038165961,1055384929,1070659201,1072570801,1074363265,1079556193,1090842145,
  94. 1093916341,1100674561,1103145121,1125038377,1131222841,1132988545,1134044821,
  95. 1136739745,1138049137,1140441121,1150270849,1152793621,1162202581,1163659861,
  96. 1177195201,1177800481,1180398961,1183104001,1189238401,1190790721,1193229577,
  97. 1194866101,1198650961,1200456577,1200778753,1206057601,1207252621,1210178305,
  98. 1213619761,1214703721,1216631521,1223475841,1227220801,1227280681,1232469001,
  99. 1251295501,1251992281,1254318481,1256855041,1257102001,1260332137,1264145401,
  100. 1268604001,1269295201,1271325841,1295577361,1299963601,1309440001,1312114945,
  101. 1312332001,1316958721,1317828601,1318126321,1321983937,1330655041,1332521065,
  102. 1337805505,1348964401,1349671681,1362132541,1376844481,1378483393,1382114881,
  103. 1384157161,1394746081,1394942473,1404111241,1404228421,1407548341,1410833281,
  104. 1419339691,1420379065,1422477001,1423668961,1428966001,1439328001,1439492041,
  105. 1441316269,1442761201,1445084173,1452767521,1481619601,1483199641,1490078305,
  106. 1490522545,1504651681,1505432881,1507746241,1515785041,1520467201,1521835381,
  107. 1528936501,1529544961,1534274841,1540454761,1545387481,1571503801,1573132561,
  108. 1574601601,1576826161,1583582113,1588247851,1592668441,1597009393,1597821121,
  109. 1615335085,1618206745,1626167341,1632785701,1641323905,1646426881,1648076041,
  110. 1657700353,1659935761,1672719217,1674309385,1676203201,1676641681,1678569121,
  111. 1685266561,1688214529,1688639041,1689411601,1690230241,1696572001,1698623641,
  112. 1699279441,1701016801,1705470481,1708549501,1726372441,1746692641,1750412161,
  113. 1752710401,1760460481,1769031901,1772267281,1773486001,1776450565,1778382541,
  114. 1784291041,1784975941,1785507361,1795216501,1801558201,1803278401,1817067169,
  115. 1825568641,1828377001,1831048561,1833328621,1836304561,1841034961,1845871105,
  116. 1846817281,1848112761,1848681121,1849811041,1854001513,1855100017,1858395529,
  117. 1879480513,1887933601,1894344001,1896961801,1899525601,1913016001,1916729101,
  118. 1918052065,1919767681,1932608161,1942608529,1943951041,1949646601,1950276565,
  119. 1954174465,1955324449,1958102641,1962804565,1976295241,1984089601,1988071801,
  120. 1992841201,1999004365,2000436751,2023528501,2029554241,2048443501,2048751901,
  121. 2049293401,2064236401,2064373921,2067887557,2073560401,2080544005,2097317377,
  122. 2101170097,2105594401,2107535221,2111416021,2111488561,2117725921,2126689501,
  123. 2140538401,2140699681,2159003281,2170282969,2176838049,2178944461,2199700321,
  124. 2199931651,2201169601,2212935985,2215407601,2216430721,2217951073,2223876601,
  125. 2224519921,2230305949,2232385345,2239622113,2244932281,2246916001,2258118721,
  126. 2265650401,2272748401,2278677961,2295209281,2301745249,2302419601,2309027281,
  127. 2313774001,2320224481,2320690177,2322648901,2323147201,2332627249,2335640077,
  128. 2339165521,2342644921,2353639681,2359686241,2361232477,2367379201,2377166401,
  129. 2391137281,2396357041,2407376665,2414829781,2430556381,2436691321,2438403661,
  130. 2443829641,2444950561,2456536681,2457411265,2467813621,2470348441,2470894273,
  131. 2479305985,2480343553,2489462641,2494465921,2494621585,2497638781,2509860961,
  132. 2510085721,2519819281,2523947041,2527812001,2529410281,2539024741,2544590161,
  133. 2547621973,2560104001,2560600351,2561945401,2564889601,2573686441,2574243721,
  134. 2575260241,2586927553,2588653081,2597928961,2598933481,2601144001,2602378721,
  135. 2605557781,2607162961,2607237361,2616662881,2617181281,2630374741,2642025673,
  136. 2657502001,2665141921,2677147201,2685422593,2690867401,2693939401,2702470861,
  137. 2709611521,2723859001,2733494401,2735309521,2766172501,2766901501,2770560241,
  138. 2776874941,2787998641,2797002901,2801124001,2806205689,2811315361,2815304401,
  139. 2832480001,2833846561,2842912381,2858298301,2867755969,2942952481,2943556201,
  140. 2965085641,2998467901,3001561441,3007991701,3022354401,3024774901,3025708561,
  141. 3030758401,3034203361,3035837161,3044238121,3044970001,3068534701,3069196417,
  142. 3072080089,3072094201,3077802001,3078386641,3086434561,3088134721,3090578401,
  143. 3102234751,3104207821,3105567361,3112974481,3119101921,3138302401,3159422785,
  144. 3159939601,3164207761,3180288385,3180632833,3188744065,3190894201,3193414093,
  145. 3203895601,3215031751,3222053185,3232450585,3240392401,3245477761,3246238801,
  146. 3248891101,3249390145,3263564305,3264820001,3270933121,3277595665,3281736601,
  147. 3284630713,3307322305,3313196881,3313744561,3314111761,3319323601,3328437481,
  148. 3345878017,3347570941,3348463105,3353809537,3378014641,3380740301,3411338491,
  149. 3413656441,3429457921,3438721441,3441837421,3480174001,3504570301,3508507801,
  150. 3521441665,3534510001,3555636481,3574014445,3575798785,3576804001,3600918181,
  151. 3618244081,3630291841,3637405045,3682471321,3697952401,3711456001,3712280041,
  152. 3713287801,3715938721,3722793481,3727589761,3754483201,3767865601,3776698801,
  153. 3787491457,3799111681,3800513761,3801823441,3805181281,3832646221,3834444901,
  154. 3835537861,3858853681,3863326897,3880251649,3891338101,3892568065,3901730401,
  155. 3907357441,3922752121,3928256641,3951813601,3981047941,3998554561,4015029061,
  156. 4030864201,4034969401,4059151489,4065133501,4077957961,4115677501,4127050621,
  157. 4134273793,4138747921,4146685921,4160472121,4162880401,4167038161,4169092201,
  158. 4169867689,4189909501,4199202001,4199529601,4199932801,4202009461,4210922233,
  159. 4212413569,4215885697,4216799521,4277982241        // 1119: 4295605861, 溢出
  160. };

  161. // hash表的改进方法, 只需要保存下标
  162. // 经测试, 最多有6次冲突, b[i][0]保存数目
  163. // 注意buckets的各维大小是人工测试得到!!

  164. static short buckets[1021][6+1];

  165. // 自动初始化hash表

  166. static struct init
  167. {
  168.         init(void)
  169.         {
  170.                 for(int i = 0; i < NELEMS(CarmichaeNumbers); ++i)
  171.                 {
  172.                         // buckets[v]类似一个栈
  173.                         // buckets[v][0]记录栈顶位置
  174.                         // 最多有6次冲突, 不会溢出

  175.                         int key = CarmichaeNumbers[i]%NELEMS(buckets);
  176.                         assert(buckets[key][0] < NELEMS(buckets[0])-1);

  177.                         buckets[key][++buckets[key][0]] = i;
  178.                 }
  179.         }
  180. } _init;

  181. // 判断是否是卡尔麦克数

  182. static bool isCarmichaelNum(unsigned n)
  183. {
  184.         // 改进: 采用hash表查找

  185.         int i, key = n%NELEMS(buckets);

  186.         for(i = 1; i <= buckets[key][0]; ++i)
  187.                 if(n == CarmichaeNumbers[buckets[key][i]]) return true;

  188.         return false;
  189. }

  190. // 计算(u*v)%m

  191. unsigned mul_mod(unsigned u, unsigned v, unsigned z)
  192. {
  193.         // 如果u*v没有溢出, 则直接计算

  194.         if((u*v)/u == v) return (u*v)%z;

  195.         // 进行长乘法(结果为64位)

  196.         unsigned u0, v0, w0;
  197.         unsigned u1, v1, w1, w2, t;

  198.         u0 = u & 0xFFFF;  u1 = u >> 16;
  199.         v0 = v & 0xFFFF;  v1 = v >> 16;
  200.         w0 = u0*v0;
  201.         t  = u1*v0 + (w0 >> 16);
  202.         w1 = t & 0xFFFF;
  203.         w2 = t >> 16;
  204.         w1 = u0*v1 + w1;

  205.         // x为高32位, y为低32位

  206.         unsigned x = u1*v1 + w2 + (w1 >> 16);
  207.         unsigned y = u*v;

  208.         // 进行长除法(被除数64位, 除数32位)

  209.         for (int i = 1; i <= 32; i++)
  210.         {
  211.                 t = (int)x >> 31;           // All 1's if x(31) = 1.

  212.                 x = (x << 1) | (y >> 31);   // Shift x || y left
  213.                 y <<= 1;                    // one bit.
  214.                
  215.                 if((x|t) >= z) { x -= z; y++; }
  216.         }

  217.         return x;        // y为商, x为余数
  218. }

  219. // 判断是否是费马(伪)素数

  220. static bool isFermatNum(unsigned p)
  221. {
  222.         unsigned m = p--;
  223.         unsigned r = 2%m;
  224.         unsigned k = 1;
  225.    
  226.         // 蒙格马利快速幂模算法

  227.         while(p > 1)
  228.         {
  229.                 if(p&1) k = mul_mod(k, r, m);
  230.                 r = mul_mod(r, r, m); p >>= 1;
  231.         }

  232.         return mul_mod(k, r, m) == 1;
  233. }

  234. // 根据费马小定理测试

  235. bool isPrime(unsigned n)
  236. {
  237.         // 处理比较特殊的情况

  238.         if(n < 2) return false;
  239.         if(n == 2) return true;
  240.         if(!(n&1)) return false;

  241.         // 是费马(伪)素数但不是卡尔麦克数则必定为素数

  242.         return isFermatNum(n) && !isCarmichaelNum(n);
  243. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-9 11:14:18 | 显示全部楼层
Post by chai2010
整理之后


  1. // 函数: bool isPrime(unsigned n);
  2. // 描述: 判断n(0, 2^32-1)是否为素数
  3. // 算法: 费马小定理-卡尔麦克数
  4. // 作者: 柴树杉
  5. // 时间: 2006-11-06
  6. // 主页: [url]chaishushan.googlepages.com[/url]

  7. #include <assert.h>
  8. #include <stdlib.h>

  9. // 计算数组的元素个数

  10. #define NELEMS(x) ((sizeof(x)) / (sizeof((x)[0])))

  11. // 2^32范围内的所有卡尔麦克数

  12. static const unsigned CarmichaeNumbers[] =
  13. {
  14. 561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,62745,
  15. 63973,75361,101101,115921,126217,162401,172081,188461,252601,278545,294409,
  16. 314821,334153,340561,399001,410041,449065,488881,512461,530881,552721,656601,
  17. 658801,670033,748657,825265,838201,852841,997633,1024651,1033669,1050985,
  18. 1082809,1152271,1193221,1461241,1569457,1615681,1773289,1857241,1909001,
  19. 2100901,2113921,2433601,2455921,2508013,2531845,2628073,2704801,3057601,
  20. 3146221,3224065,3581761,3664585,3828001,4335241,4463641,4767841,4903921,
  21. 4909177,5031181,5049001,5148001,5310721,5444489,5481451,5632705,5968873,
  22. 6049681,6054985,6189121,6313681,6733693,6840001,6868261,7207201,7519441,
  23. 7995169,8134561,8341201,8355841,8719309,8719921,8830801,8927101,9439201,
  24. 9494101,9582145,9585541,9613297,9890881,10024561,10267951,10402561,10606681,
  25. 10837321,10877581,11119105,11205601,11921001,11972017,12261061,12262321,
  26. 12490201,12945745,13187665,13696033,13992265,14469841,14676481,14913991,
  27. 15247621,15403285,15829633,15888313,16046641,16778881,17098369,17236801,
  28. 17316001,17586361,17812081,18162001,18307381,18900973,19384289,19683001,
  29. 20964961,21584305,22665505,23382529,25603201,26280073,26474581,26719701,
  30. 26921089,26932081,27062101,27336673,27402481,28787185,29020321,29111881,
  31. 31146661,31405501,31692805,32914441,33302401,33596641,34196401,34657141,
  32. 34901461,35571601,35703361,36121345,36765901,37167361,37280881,37354465,
  33. 37964809,38151361,38624041,38637361,39353665,40160737,40280065,40430401,
  34. 40622401,40917241,41298985,41341321,41471521,42490801,43286881,43331401,
  35. 43584481,43620409,44238481,45318561,45877861,45890209,46483633,47006785,
  36. 48321001,48628801,49333201,50201089,53245921,53711113,54767881,55462177,
  37. 56052361,58489201,60112885,60957361,62756641,64377991,64774081,65037817,
  38. 65241793,67371265,67653433,67902031,67994641,68154001,69331969,70561921,
  39. 72108421,72286501,74165065,75151441,75681541,75765313,76595761,77826001,
  40. 78091201,78120001,79411201,79624621,80282161,80927821,81638401,81926461,
  41. 82929001,83099521,83966401,84311569,84350561,84417985,87318001,88689601,
  42. 90698401,92625121,93030145,93614521,93869665,94536001,96895441,99036001,
  43. 99830641,99861985,100427041,101649241,101957401,102090781,104404861,104569501,
  44. 104852881,105117481,105309289,105869401,106041937,107714881,109393201,109577161,
  45. 111291181,114910489,115039081,115542505,116682721,118901521,119327041,120981601,
  46. 121247281,122785741,124630273,127664461,128697361,129255841,129762001,130032865,
  47. 130497361,132511681,133205761,133344793,133800661,134809921,134857801,135556345,
  48. 136625941,139592101,139952671,140241361,144218341,145124785,146843929,150846961,
  49. 151530401,151813201,153589801,153927961,157731841,158404141,158864833,159492061,
  50. 161035057,161242705,161913961,163954561,167979421,168659569,169057801,169570801,
  51. 170947105,171454321,171679561,172290241,172430401,172947529,173085121,174352641,
  52. 175997185,176659201,178451857,178482151,178837201,180115489,181154701,182356993,
  53. 184353001,186393481,186782401,187188001,188516329,188689501,189941761,193708801,
  54. 193910977,194120389,194675041,196358977,200753281,206955841,208969201,212027401,
  55. 213835861,214850881,214852609,216821881,221884001,225745345,226509361,227752993,
  56. 228842209,230630401,230996949,231194965,237597361,238244041,238527745,241242001,
  57. 242641153,246446929,247095361,250200721,252141121,255160621,256828321,257495641,
  58. 258634741,266003101,270857521,271481329,271794601,273769921,274569601,275283401,
  59. 277241401,278152381,279377281,280067761,280761481,288120421,289766701,289860481,
  60. 291848401,292244833,292776121,295643089,295826581,296559361,299736181,300614161,
  61. 301704985,302751505,306871201,311388337,318266641,321197185,321602401,325546585,
  62. 328573477,329769721,333065305,333229141,334783585,338740417,346808881,348612265,
  63. 354938221,357277921,357380101,358940737,360067201,362569201,364590721,366532321,
  64. 366652201,367804801,367939585,368113411,382304161,382536001,390489121,392099401,
  65. 393122521,393513121,393716701,395044651,395136505,396262945,399906001,403043257,
  66. 403317421,405739681,413058601,413138881,413631505,416964241,417241045,419520241,
  67. 426821473,429553345,434330401,434932961,438359041,440306461,440707345,455106601,
  68. 458368201,461502097,461854261,462199681,471441001,471905281,473847121,477726145,
  69. 481239361,483006889,484662529,490099681,490503601,492559141,496050841,499310197,
  70. 503758801,507726901,509033161,510825601,511338241,516684961,517937581,518117041,
  71. 518706721,527761081,529782121,530443201,532758241,533860309,540066241,542497201,
  72. 544101481,545363281,545570641,547652161,548871961,549117205,549333121,549538081,
  73. 551672221,552894301,555465601,556199281,556450777,557160241,557795161,558570961,
  74. 558977761,561481921,561777121,564651361,568227241,569332177,573896881,577240273,
  75. 579606301,580565233,590754385,593234929,595405201,597717121,600892993,602074585,
  76. 602426161,602593441,606057985,609865201,611397865,612347905,612816751,616463809,
  77. 618068881,620169409,621101185,625060801,625482001,629692801,631071001,633639097,
  78. 638959321,642708001,652969351,656187001,662086041,672389641,683032801,683379841,
  79. 684106401,686059921,689880801,697906561,698548201,702683101,703995733,704934361,
  80. 705101761,707926801,710382401,710541481,711374401,713588401,717164449,721244161,
  81. 722923201,727083001,739444021,743404663,744866305,745864945,746706961,752102401,
  82. 759472561,765245881,771043201,775368901,775866001,776176261,781347841,784966297,
  83. 790020001,790623289,794937601,798770161,804978721,809702401,809883361,814056001,
  84. 822531841,824389441,824405041,829678141,832060801,833608321,834244501,834720601,
  85. 836515681,839275921,841340521,842202361,843704401,847491361,849064321,851703301,
  86. 851934601,852729121,854197345,855734401,860056705,863984881,867800701,868234081,
  87. 876850801,882796321,885336481,888700681,891706861,897880321,902645857,914801665,
  88. 918661501,928482241,930745621,931694401,934784929,935794081,939947009,940123801,
  89. 941056273,945959365,947993761,954732853,955134181,957044881,958735681,958762729,
  90. 958970545,962442001,962500561,963163201,963168193,968553181,968915521,975303121,
  91. 977737321,977892241,981567505,981789337,985052881,986088961,990893569,993420289,
  92. 993905641,1001152801,1018928485,1027334881,1030401901,1031750401,1035608041,
  93. 1038165961,1055384929,1070659201,1072570801,1074363265,1079556193,1090842145,
  94. 1093916341,1100674561,1103145121,1125038377,1131222841,1132988545,1134044821,
  95. 1136739745,1138049137,1140441121,1150270849,1152793621,1162202581,1163659861,
  96. 1177195201,1177800481,1180398961,1183104001,1189238401,1190790721,1193229577,
  97. 1194866101,1198650961,1200456577,1200778753,1206057601,1207252621,1210178305,
  98. 1213619761,1214703721,1216631521,1223475841,1227220801,1227280681,1232469001,
  99. 1251295501,1251992281,1254318481,1256855041,1257102001,1260332137,1264145401,
  100. 1268604001,1269295201,1271325841,1295577361,1299963601,1309440001,1312114945,
  101. 1312332001,1316958721,1317828601,1318126321,1321983937,1330655041,1332521065,
  102. 1337805505,1348964401,1349671681,1362132541,1376844481,1378483393,1382114881,
  103. 1384157161,1394746081,1394942473,1404111241,1404228421,1407548341,1410833281,
  104. 1419339691,1420379065,1422477001,1423668961,1428966001,1439328001,1439492041,
  105. 1441316269,1442761201,1445084173,1452767521,1481619601,1483199641,1490078305,
  106. 1490522545,1504651681,1505432881,1507746241,1515785041,1520467201,1521835381,
  107. 1528936501,1529544961,1534274841,1540454761,1545387481,1571503801,1573132561,
  108. 1574601601,1576826161,1583582113,1588247851,1592668441,1597009393,1597821121,
  109. 1615335085,1618206745,1626167341,1632785701,1641323905,1646426881,1648076041,
  110. 1657700353,1659935761,1672719217,1674309385,1676203201,1676641681,1678569121,
  111. 1685266561,1688214529,1688639041,1689411601,1690230241,1696572001,1698623641,
  112. 1699279441,1701016801,1705470481,1708549501,1726372441,1746692641,1750412161,
  113. 1752710401,1760460481,1769031901,1772267281,1773486001,1776450565,1778382541,
  114. 1784291041,1784975941,1785507361,1795216501,1801558201,1803278401,1817067169,
  115. 1825568641,1828377001,1831048561,1833328621,1836304561,1841034961,1845871105,
  116. 1846817281,1848112761,1848681121,1849811041,1854001513,1855100017,1858395529,
  117. 1879480513,1887933601,1894344001,1896961801,1899525601,1913016001,1916729101,
  118. 1918052065,1919767681,1932608161,1942608529,1943951041,1949646601,1950276565,
  119. 1954174465,1955324449,1958102641,1962804565,1976295241,1984089601,1988071801,
  120. 1992841201,1999004365,2000436751,2023528501,2029554241,2048443501,2048751901,
  121. 2049293401,2064236401,2064373921,2067887557,2073560401,2080544005,2097317377,
  122. 2101170097,2105594401,2107535221,2111416021,2111488561,2117725921,2126689501,
  123. 2140538401,2140699681,2159003281,2170282969,2176838049,2178944461,2199700321,
  124. 2199931651,2201169601,2212935985,2215407601,2216430721,2217951073,2223876601,
  125. 2224519921,2230305949,2232385345,2239622113,2244932281,2246916001,2258118721,
  126. 2265650401,2272748401,2278677961,2295209281,2301745249,2302419601,2309027281,
  127. 2313774001,2320224481,2320690177,2322648901,2323147201,2332627249,2335640077,
  128. 2339165521,2342644921,2353639681,2359686241,2361232477,2367379201,2377166401,
  129. 2391137281,2396357041,2407376665,2414829781,2430556381,2436691321,2438403661,
  130. 2443829641,2444950561,2456536681,2457411265,2467813621,2470348441,2470894273,
  131. 2479305985,2480343553,2489462641,2494465921,2494621585,2497638781,2509860961,
  132. 2510085721,2519819281,2523947041,2527812001,2529410281,2539024741,2544590161,
  133. 2547621973,2560104001,2560600351,2561945401,2564889601,2573686441,2574243721,
  134. 2575260241,2586927553,2588653081,2597928961,2598933481,2601144001,2602378721,
  135. 2605557781,2607162961,2607237361,2616662881,2617181281,2630374741,2642025673,
  136. 2657502001,2665141921,2677147201,2685422593,2690867401,2693939401,2702470861,
  137. 2709611521,2723859001,2733494401,2735309521,2766172501,2766901501,2770560241,
  138. 2776874941,2787998641,2797002901,2801124001,2806205689,2811315361,2815304401,
  139. 2832480001,2833846561,2842912381,2858298301,2867755969,2942952481,2943556201,
  140. 2965085641,2998467901,3001561441,3007991701,3022354401,3024774901,3025708561,
  141. 3030758401,3034203361,3035837161,3044238121,3044970001,3068534701,3069196417,
  142. 3072080089,3072094201,3077802001,3078386641,3086434561,3088134721,3090578401,
  143. 3102234751,3104207821,3105567361,3112974481,3119101921,3138302401,3159422785,
  144. 3159939601,3164207761,3180288385,3180632833,3188744065,3190894201,3193414093,
  145. 3203895601,3215031751,3222053185,3232450585,3240392401,3245477761,3246238801,
  146. 3248891101,3249390145,3263564305,3264820001,3270933121,3277595665,3281736601,
  147. 3284630713,3307322305,3313196881,3313744561,3314111761,3319323601,3328437481,
  148. 3345878017,3347570941,3348463105,3353809537,3378014641,3380740301,3411338491,
  149. 3413656441,3429457921,3438721441,3441837421,3480174001,3504570301,3508507801,
  150. 3521441665,3534510001,3555636481,3574014445,3575798785,3576804001,3600918181,
  151. 3618244081,3630291841,3637405045,3682471321,3697952401,3711456001,3712280041,
  152. 3713287801,3715938721,3722793481,3727589761,3754483201,3767865601,3776698801,
  153. 3787491457,3799111681,3800513761,3801823441,3805181281,3832646221,3834444901,
  154. 3835537861,3858853681,3863326897,3880251649,3891338101,3892568065,3901730401,
  155. 3907357441,3922752121,3928256641,3951813601,3981047941,3998554561,4015029061,
  156. 4030864201,4034969401,4059151489,4065133501,4077957961,4115677501,4127050621,
  157. 4134273793,4138747921,4146685921,4160472121,4162880401,4167038161,4169092201,
  158. 4169867689,4189909501,4199202001,4199529601,4199932801,4202009461,4210922233,
  159. 4212413569,4215885697,4216799521,4277982241        // 1119: 4295605861, 溢出
  160. };

  161. // hash表的改进方法, 只需要保存下标
  162. // 经测试, 最多有6次冲突, b[i][0]保存数目
  163. // 注意buckets的各维大小是人工测试得到!!

  164. static short buckets[1021][6+1];

  165. // 自动初始化hash表

  166. static struct init
  167. {
  168.         init(void)
  169.         {
  170.                 for(int i = 0; i < NELEMS(CarmichaeNumbers); ++i)
  171.                 {
  172.                         // buckets[v]类似一个栈
  173.                         // buckets[v][0]记录栈顶位置
  174.                         // 最多有6次冲突, 不会溢出

  175.                         int key = CarmichaeNumbers[i]%NELEMS(buckets);
  176.                         assert(buckets[key][0] < NELEMS(buckets[0])-1);

  177.                         buckets[key][++buckets[key][0]] = i;
  178.                 }
  179.         }
  180. } _init;

  181. // 判断是否是卡尔麦克数

  182. static bool isCarmichaelNum(unsigned n)
  183. {
  184.         // 改进: 采用hash表查找

  185.         int i, key = n%NELEMS(buckets);

  186.         for(i = 1; i <= buckets[key][0]; ++i)
  187.                 if(n == CarmichaeNumbers[buckets[key][i]]) return true;

  188.         return false;
  189. }

  190. // 计算(u*v)%m

  191. unsigned mul_mod(unsigned u, unsigned v, unsigned z)
  192. {
  193.         // 如果u*v没有溢出, 则直接计算

  194.         if((u*v)/u == v) return (u*v)%z;

  195.         // 进行长乘法(结果为64位)

  196.         unsigned u0, v0, w0;
  197.         unsigned u1, v1, w1, w2, t;

  198.         u0 = u & 0xFFFF;  u1 = u >> 16;
  199.         v0 = v & 0xFFFF;  v1 = v >> 16;
  200.         w0 = u0*v0;
  201.         t  = u1*v0 + (w0 >> 16);
  202.         w1 = t & 0xFFFF;
  203.         w2 = t >> 16;
  204.         w1 = u0*v1 + w1;

  205.         // x为高32位, y为低32位

  206.         unsigned x = u1*v1 + w2 + (w1 >> 16);
  207.         unsigned y = u*v;

  208.         // 进行长除法(被除数64位, 除数32位)

  209.         for (int i = 1; i <= 32; i++)
  210.         {
  211.                 t = (int)x >> 31;           // All 1's if x(31) = 1.

  212.                 x = (x << 1) | (y >> 31);   // Shift x || y left
  213.                 y <<= 1;                    // one bit.
  214.                
  215.                 if((x|t) >= z) { x -= z; y++; }
  216.         }

  217.         return x;        // y为商, x为余数
  218. }

  219. // 判断是否是费马(伪)素数

  220. static bool isFermatNum(unsigned p)
  221. {
  222.         unsigned m = p--;
  223.         unsigned r = 2%m;
  224.         unsigned k = 1;
  225.    
  226.         // 蒙格马利快速幂模算法

  227.         while(p > 1)
  228.         {
  229.                 if(p&1) k = mul_mod(k, r, m);
  230.                 r = mul_mod(r, r, m); p >>= 1;
  231.         }

  232.         return mul_mod(k, r, m) == 1;
  233. }

  234. // 根据费马小定理测试

  235. bool isPrime(unsigned n)
  236. {
  237.         // 处理比较特殊的情况

  238.         if(n < 2) return false;
  239.         if(n == 2) return true;
  240.         if(!(n&1)) return false;

  241.         // 是费马(伪)素数但不是卡尔麦克数则必定为素数

  242.         return isFermatNum(n) && !isCarmichaelNum(n);
  243. }
复制代码


这个方法其实还有缺陷,主要因为之前概念理解有错误。
卡尔麦克数是针对所有Zn*费马测试为真的情况!
因此,基于2(或者其他值)的伪素数,除了卡尔麦克数之外还有别的。
比如:341。这个之前都没有考虑到。

不过,即使只针对2的情况,伪素数还是比较少的,
可以在我们期望的一个范围内。
那样,依然可以保存基于2的所有伪素数表。

当然,生成2^32之内的2的伪素数可能要花些时间
(我采用的是比较普通的方法)

下次我将给出生成2的伪素数和一些自动测试的代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-9 11:26:43 | 显示全部楼层
开始的方法代码也可以这样
  1. // 计算数组的元素个数
  2. #define NELEMS(x) ((sizeof(x)) / (sizeof((x)[0])))
  3. // 构造素数序列primes[]
  4. void makePrimes(int primes[], int num)
  5. {
  6.         primes[0] = 2;
  7.    
  8.         for(int p = 3, cnt = 1; cnt < num; p += 2)
  9.         {
  10.                 for(int k = 1; ; ++k)
  11.                 {
  12.                         // 可以在div时得到余数
  13.                         // assert(p <= INT_MAX);
  14.                         div_t dt = div(p, primes[k]);
  15.                         if(dt.rem == 0) break;
  16.                         if(dt.quot <= primes[k]) { primes[cnt++] = p; break; }
  17.                 }
  18.         }
  19. }
  20. // 其他算法判断素数, 用于测试
  21. bool isPrime(unsigned p)
  22. {
  23.         // 静态初始化素数序列
  24.         static int px[1024*8];
  25.         static struct Init {
  26.                 Init(int *p, int n){makePrimes(p, n);}
  27.         } _init(px, NELEMS(px));
  28.         // 处理特殊情况
  29.         if(p < 2) return false;
  30.         if(p == 2) return true;
  31.         if(!(p&1)) return false;
  32.         // 测试px[i]是否为其因子
  33.         for(int k = 1; px[k]*px[k] <= p; ++k)
  34.         {
  35.                 if(p%px[k] == 0) return false;
  36.         }
  37.         return true;
  38. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-9 11:41:35 | 显示全部楼层
测试程序


  1. #include <assert.h>
  2. #include <stdlib.h>
  3. #include <time.h>

  4. bool Test_isPrime(unsigned p)
  5. {
  6.         // 其他方法判断
  7. }

  8. int main(int max)
  9. {
  10.         srand(time(NULL));

  11.         for(unsigned i = 0; i < max; ++i)
  12.         {
  13.                 unsigned p = (rand()<<16) | rand();
  14.                 assert(isPrime(p) == Test_isPrime(p));
  15.         }
  16. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-9 14:48:19 | 显示全部楼层
生成2^32以内基于2的费马伪素数


  1. // 缺少的函数参考前面的帖子
  2. // 测试(1, 2^32)内所有基于2的费马伪素数
  3. // 偶数的情况没有测试

  4. int main()
  5. {
  6.         unsigned i, cnt = 0;

  7.         for(i = 1; i <= UINT_MAX; i += 2)
  8.         {
  9.                 if(isPrime(i) && (!Test_isPrime(i)))
  10.                 {
  11.                         printf("%d: %u\n", ++cnt, i);
  12.                 }
  13.         }

  14.         return 0;
  15. }
复制代码


可以将输出重定向到文件中: ./a.out > data.txt

由于耗时比较长,最好是在机器空闲的时候跑:-)
我打算晚上让机器跑一夜,有结果在发上来...
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-10 13:32:00 | 显示全部楼层
这里有基于2的费马伪素数,

http://www.research.att.com/~njas/sequences/b001567.txt
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-10 14:48:45 | 显示全部楼层
修改后的代码



  1. // 函数: bool isPrime(unsigned n);
  2. // 描述: 判断n(0, 2^32-1)是否为素数
  3. // 算法: 费马小定理剔除伪素数
  4. // 作者: 柴树杉
  5. // 时间: 2006-11-06
  6. // 主页: [url]chaishushan.googlepages.com[/url]

  7. #include "FermatPrime.h"

  8. #include <assert.h>
  9. #include <stdlib.h>

  10. // 计算数组的元素个数

  11. #define NELEMS(x) ((sizeof(x)) / (sizeof((x)[0])))

  12. // 2^32之内基于2的费马伪素数

  13. static const unsigned FermatPseudoprimes[] =
  14. {
  15. 341,561,645,1105,1387,1729,1905,2047,2465,2701,2821,3277,4033,4369,4371,
  16. 4681,5461,6601,7957,8321,8481,8911,10261,10585,11305,12801,13741,13747,
  17. 13981,14491,15709,15841,16705,18705,18721,19951,23001,23377,25761,29341,
  18. 30121,30889,31417,31609,31621,33153,34945,35333,39865,41041,41665,42799,
  19. 46657,49141,49981,52633,55245,57421,60701,60787,62745,63973,65077,65281,
  20. 68101,72885,74665,75361,80581,83333,83665,85489,87249,88357,88561,90751,
  21. 91001,93961,101101,104653,107185,113201,115921,121465,123251,126217,129889,
  22. 129921,130561,137149,149281,150851,154101,157641,158369,162193,162401,164737,

  23. // ... 缺少的伪素数请访问:
  24. // [url]http://www.research.att.com/~njas/sequences/b001567.txt[/url]

  25. 4284050473,4285148981,4286383201,4286813749,4288664869,4289470021,4289641621,
  26. 4289884201,4289906089,4293088801,4293329041,4294868509,4294901761
  27. };        // num = 10403

  28. // 构造hash表

  29. static short buckets[10427];
  30. static short link[NELEMS(FermatPseudoprimes)];

  31. // 建立hash表, 只运行一次
  32. // hash的最大冲突为7次

  33. static void initBuckets(void)
  34. {
  35.         int max = 0;
  36.         for(int i = 0; i < NELEMS(FermatPseudoprimes); ++i)
  37.         {
  38.                 int h = FermatPseudoprimes[i]%NELEMS(buckets);

  39.                 { link[i] = buckets[h]; buckets[h] = i + 1; }
  40.         }
  41. }

  42. // 判断是否是费马伪素数

  43. static bool isFermatPseudoprime(unsigned p)
  44. {
  45.         // 静态调用initBuckets函数

  46.         static struct Init {
  47.                 Init(){initBuckets();} } _init;

  48.         // 在hash表中查找

  49.         int h = p%NELEMS(buckets);
  50.         int next = buckets[h]-1;

  51.         for( ; next >= 0; next = link[next]-1)
  52.         {
  53.                 if(p == FermatPseudoprimes[next]) return true;
  54.         }
  55.         return false;
  56. }

  57. // 计算(u*v)%m

  58. unsigned mul_mod(unsigned u, unsigned v, unsigned z)
  59. {
  60.         // 如果u*v没有溢出, 则直接计算

  61.         if((u*v)/u == v) return (u*v)%z;

  62.         // 进行长乘法(结果为64位)

  63.         unsigned u0, v0, w0;
  64.         unsigned u1, v1, w1, w2, t;

  65.         u0 = u & 0xFFFF;  u1 = u >> 16;
  66.         v0 = v & 0xFFFF;  v1 = v >> 16;
  67.         w0 = u0*v0;
  68.         t  = u1*v0 + (w0 >> 16);
  69.         w1 = t & 0xFFFF;
  70.         w2 = t >> 16;
  71.         w1 = u0*v1 + w1;

  72.         // x为高32位, y为低32位

  73.         unsigned x = u1*v1 + w2 + (w1 >> 16);
  74.         unsigned y = u*v;

  75.         // 进行长除法(除数为64位)

  76.         for (int i = 1; i <= 32; i++)
  77.         {
  78.                 t = (int)x >> 31;           // All 1's if x(31) = 1.

  79.                 x = (x << 1) | (y >> 31);   // Shift x || y left
  80.                 y <<= 1;                    // one bit.
  81.                
  82.                 if((x|t) >= z) { x -= z; y++; }
  83.         }

  84.         return x;        // y为商, x为余数
  85. }

  86. // 判断是否是费马(伪)素数

  87. static bool isFermatNum(unsigned p)
  88. {
  89.         unsigned m = p--;
  90.         unsigned r = 2%m;
  91.         unsigned k = 1;
  92.    
  93.         // 蒙格马利快速幂模算法

  94.         while(p > 1)
  95.         {
  96.                 if(p&1) k = mul_mod(k, r, m);
  97.                 r = mul_mod(r, r, m); p >>= 1;
  98.         }

  99.         return mul_mod(k, r, m) == 1;
  100. }

  101. // 根据费马小定理测试

  102. bool isPrime(unsigned n)
  103. {
  104.         // 处理比较特殊的情况

  105.         if(n < 2) return false;
  106.         if(n == 2) return true;
  107.         if(!(n&1)) return false;

  108.         // 从费马(伪)素数剔除伪素数情况

  109.         return isFermatNum(n) && !isFermatPseudoprime(n);
  110. }


复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-15 17:48:13 | 显示全部楼层
在第1帖 9 中, 作为副产品曾提供以下2个函数:

extern int  Prime_max(void);        // 素数序列的大小
extern int  Prime_get (int i);        // 返回第i个素数, 0 <= i < Prime_max

Prime_max返回缓冲的素数序列大小,
Prime_get则可以从缓冲的序列中获取一定的素数。

其实Prime_get完全可以返回2^32范围内任意素数!

另外,还可以提供Prime_num(unsigned max);用于返回
1-max之间素数的个数(也用于实现Prime_get函数)。

具体的细节和代码下次慢慢补充...
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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