找回密码
 欢迎注册
楼主: 无心人

[讨论] 极大素数间隔问题

[复制链接]
发表于 2008-3-19 15:31:34 | 显示全部楼层
不妨定义这样的需求,或许更有用些。 对于每一个偶数K, 求出相邻的质数对(p1,p2),使得p2-p1=K 且 p2 尽可能小。 如对于K=2, p1=3, p2=5 K=4, p1=7, p2=11 K=14, p1=113, p2=127
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-19 19:32:09 | 显示全部楼层
原帖由 liangbch 于 2008-3-19 15:31 发表 不妨定义这样的需求,或许更有用些。 对于每一个偶数K, 求出相邻的质数对(p1,p2),使得p2-p1=K 且 p2 尽可能小。 如对于K=2, p1=3, p2=5 K=4, p1=7, p2=11 K=14, p1=113, p2=127
感觉改成使“p1 尽可能小”更恰当,与其它参考资料比较相融。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-20 09:10:25 | 显示全部楼层
一个模子扣出来的题目 并没有区别啊 也不见得更容易 假设求k=2000的,如何操作? 肯定在50位以内, 32位以上
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-20 11:41:27 | 显示全部楼层
原帖由 无心人 于 2008-3-20 09:10 发表 一个模子扣出来的题目 并没有区别啊 也不见得更容易
我没有仔细看题目,实际上我的需求和你的是一致的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-21 09:24:30 | 显示全部楼层

可爱的程序终于在CSDN搜索到了 :)

  1. program p27;
  2. //发现在10^14以内的极大素数间隔
  3. type
  4. primearray = array[1..664800] of longword;
  5. primesieve = array[1..4 * 3 * 5 * 7 * 11 * 13 * 17 * 19] of byte;
  6. const
  7. c01: double = 0.5;
  8. var
  9. p: primesieve;
  10. t: primesieve;
  11. sp: primearray;
  12. lp, rp: int64;
  13. start, stop: int64;
  14. prev: int64;
  15. pf: TextFile;
  16. s, csp: integer;
  17. cpuA, cpuB: int64;
  18. procedure compsieve;
  19. var
  20. i, j: integer;
  21. pp: array[1..8] of integer;
  22. begin
  23. pp[1] := 2;
  24. pp[2] := 3;
  25. pp[3] := 5;
  26. pp[4] := 7;
  27. pp[5] := 11;
  28. pp[6] := 13;
  29. pp[7] := 17;
  30. pp[8] := 19;
  31. for i := 1 to 4 * 3 * 5 * 7 * 11 * 13 * 17 * 19 do
  32. begin
  33. t[ i ] := 1;
  34. for j := 1 to 8 do
  35. if i mod pp[j] = 0 then
  36. begin
  37. t[ i ] := 0;
  38. end;
  39. end;
  40. end;
  41. procedure comptemp;
  42. var
  43. tf: file of primesieve;
  44. begin
  45. assignfile(tf, 'psieve.dat');
  46. {\$I-}
  47. reset(tf);
  48. read(tf, t);
  49. close(tf);
  50. {\$I+}
  51. if IOResult <> 0 then
  52. begin
  53. compsieve;
  54. rewrite(tf);
  55. write(tf, t);
  56. closefile(tf);
  57. end;
  58. end;
  59. procedure loadtemp;
  60. begin
  61. move(t, p, sizeof(p));
  62. end;
  63. function IsPrime(TestPrime: int64): boolean;
  64. var
  65. i: integer;
  66. k: int64;
  67. begin
  68. i := 1;
  69. k := round(sqrt(TestPrime * 1.0) + 0.5);
  70. while sp[ i ] <= k do
  71. begin
  72. if TestPrime mod sp[ i ] = 0 then
  73. begin
  74. IsPrime := False;
  75. exit;
  76. end;
  77. inc(i);
  78. end;
  79. IsPrime := True;
  80. end;
  81. procedure getcputime(var cputime: int64);
  82. begin
  83. asm
  84. push ebx
  85. push eax
  86. db \$0f, \$31
  87. mov ebx, eax
  88. pop eax
  89. mov dword ptr [eax], ebx
  90. mov dword ptr [eax + 4], edx
  91. pop ebx
  92. end;
  93. end;
  94. procedure findsmallprime;
  95. var
  96. i, j, k: longword;
  97. begin
  98. sp[1] := 3;
  99. sp[2] := 5;
  100. sp[3] := 7;
  101. sp[4] := 11;
  102. csp := 4;
  103. k := 13;
  104. while (k <= 9999999) do
  105. begin
  106. j := 1;
  107. i := round(sqrt(k) + 0.5);
  108. while sp[j] <= i do
  109. begin
  110. if k mod sp[j] = 0 then break;
  111. inc(j);
  112. end;
  113. if k mod sp[j] <> 0 then
  114. begin
  115. inc(csp);
  116. sp[csp] := k;
  117. end;
  118. k := k + 2;
  119. end;
  120. end;
  121. procedure loadprime;
  122. var
  123. p: file of primearray;
  124. begin
  125. assignfile(p, 'prime.dat');
  126. {\$I-}
  127. reset(p);
  128. read(p, sp);
  129. {\$I+}
  130. if IOResult <> 0 then
  131. begin
  132. FindSmallPrime;
  133. rewrite(p);
  134. write(p, sp);
  135. end;
  136. csp := 664578;
  137. closefile(p);
  138. end;
  139. procedure sieve;
  140. var
  141. j, k, n: int64;
  142. i, l: integer;
  143. m: longword;
  144. tmp1: longword;
  145. tmp2: longword;
  146. begin
  147. stop := start + 4 * 3 * 5 * 7 * 11 * 13 * 17 * 19 - 1;
  148. // getcputime(cpuA);
  149. loadtemp;
  150. //m := round(sqrt(stop * 1.0)+0.5)
  151. asm
  152. fild qword ptr [stop]
  153. fsqrt
  154. fadd qword ptr [c01]
  155. fistp dword ptr [m]
  156. end;
  157. i := 8;
  158. repeat
  159. tmp2 := sp[ i ];
  160. tmp1 := tmp2 * 2;
  161. n := tmp2 * tmp2;
  162. if n < start then j := start else j := n;
  163. // k := (j div tmp2) * tmp2;
  164. asm
  165. push ebx
  166. push ecx
  167. mov edx, 0
  168. mov eax, dword ptr [j + 4]
  169. mov ecx, tmp2
  170. div ecx
  171. mov ebx, eax
  172. mov eax, dword ptr [j]
  173. div ecx
  174. mul ecx
  175. mov dword ptr [k], eax
  176. mov eax, ebx
  177. mov ebx, edx
  178. mul ecx
  179. add eax, ebx
  180. mov dword ptr [k + 4], eax
  181. pop ecx
  182. pop ebx
  183. end;
  184. if k < start then k := k + tmp2;
  185. if k mod 2 = 0 then k := k + tmp2;
  186. while (k <= stop) do
  187. begin
  188. if p[k- start + 1] <> 0 then
  189. p[k - start + 1] := 0;
  190. k := k + tmp1;
  191. end;
  192. inc(i);
  193. until (sp[ i ] > m) or (i > csp);
  194. // getcputime(cpuB);
  195. // writeln(' Sieve cpu code time:', cpuB - cpuA);
  196. l := prev - start + 1;
  197. for i := 1 to 4 * 3 * 5 * 7 * 11 * 13 * 17 * 19 do
  198. begin
  199. if p[ i ] = 1 then
  200. begin
  201. if i - l >= s then
  202. begin
  203. lp := start + l - 1; rp := start + i - 1; s := i - l;
  204. writeln;
  205. writeln(lp:14, rp:14, s:14);
  206. writeln(pf, lp:14, rp:14, s:14);
  207. flush(pf);
  208. end;
  209. l := i;
  210. end;
  211. end;
  212. prev := start + l - 1;
  213. start := stop + 1;
  214. end;
  215. var
  216. bf: TextFile;
  217. bk: longword;
  218. begin
  219. loadprime;
  220. // writeln('加载素数表成功!');
  221. comptemp;
  222. // writeln('准备模版成功!');
  223. bk := 1;
  224. assignfile(bf, 'prime.ini');
  225. {\$I-}
  226. reset(bf);
  227. readln(bf, Start);
  228. if start mod 19399380 <> 1 then
  229. start := (start div 19399380) * 19399380 + 1;
  230. readln(bf, s);
  231. closefile(bf);
  232. {\$I+}
  233. if IOResult <> 0 then
  234. begin
  235. start := int64(17071454401);
  236. s := 382;
  237. end;
  238. Prev := Start;
  239. while not IsPrime(Prev) do
  240. Prev := Prev - 2;
  241. // writeln('加载开始点成功,start = ', start:14, ', prev = ', prev:14);
  242. assignfile(pf, 'p2.txt');
  243. append(pf);
  244. repeat
  245. sieve;
  246. // write('.');
  247. // writeln('现在进行下一个循环! prev = ', prev);
  248. inc(bk);
  249. if bk >= 100 then
  250. begin
  251. bk := 1;
  252. rewrite(bf);
  253. writeln(bf, start);
  254. writeln(bf, s);
  255. closefile(bf);
  256. end;
  257. until prev >= int64(100000000000000);
  258. closefile(pf);
  259. end.
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-21 09:41:16 | 显示全部楼层
17071454401 = 880*19399380+1 为什么要从这里开始?有什么先验知识在这里? 还有为什么选择4 * 3 * 5 * 7 * 11 * 13 * 17 * 19,其实应该 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19就可以了呀?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-21 09:58:20 | 显示全部楼层
哈 因为是之前的已计算了啊 至于选4 * 3 * 5 * 7 * 11 * 13 * 17 * 19因为是32位整数的倍数 是02年4月的东西, 现在肯定不这么写
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-24 11:03:34 | 显示全部楼层
原帖由 无心人 于 2008-3-19 13:55 发表 我能调度 但做仔细的编码 1、没相关算法 2、手里的汇编优化资料全E文的, 理解有困难 3、通过这几个星期的练习汇编功力还有待加强啊
这个算法不是问题,袁本身的算法他大概描述过,其实不是很复杂。 我们可以认为分成两个部分,第一部分是搜索过程,对于每个给定的低N/4位,可以唯一确定开平方后的结果(基本唯一确定)。对于这部分代码,袁的算法不算最优,我们可以继续优化到基本上不出现乘法运算。 但是,在找到开平方后的结果,我们还需要验证这个结果是否正确的,而这部分验证过程的时间复杂度和上面过程是相同的,但是其中乘法计算(相当于一个比较大的整数的平方计算,基本上是20到30位的10进制数的平方,最好有快速的10进制计算)我没法优化掉,所以这一部分的时间很难优化掉。也正因为这样,我觉得要远远超越他的结果很难,但是考虑到你们可以对乘法做很好的优化的话(不知道比普通C代码写出来可以快多少倍),那么应该可以平均速度比他快一些。 但是在算法复杂度上,并没有明显的改变。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-24 16:02:16 | 显示全部楼层
如果测算乘法 8位一组 极限情况下,就是32位4组乘了 如果有好算法能快速从 x * (2^64 / 10^8)中得到 x / 10^8 商,那10进乘法并不困难,否则可能时间是二进乘法的2倍甚至更多 ======================================= 或者做6位一组的乘,这个纠正系数是10995很小了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-24 16:21:00 | 显示全部楼层
这个div by constant转化为乘法总是可以做的,你可以让C编译器编译一下,看优化以后的汇编代码就应该能够得到
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-21 21:03 , Processed in 0.034238 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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