- 注册时间
- 2007-12-28
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 12787
- 在线时间
- 小时
|
发表于 2008-3-21 14:21:24
|
显示全部楼层
原帖由 无心人 于 2008-3-17 15:06 发表
我觉得并不比不压缩的字节表示快
也应该慢于位数组
筛法求素数主要算法是:
1.预置一个数组,初始化为所有的数都是合数,然后筛去素数的倍数。
2.关于数组的表示方法,我知道的有BYTE数组(每个BYTE表示一个数),bit数组(每个bit表示一个数,若要筛n个数
,只需要n/8字节),压缩的bit数组3种.对于压缩的bit数组,每个bit只对应一些可能的素数,对一些明显不是素数的则
没有对应的bit,如bit值对应形为2K+1的或者形为30K+(1,7,11,13,17,19,23,29)的数,后者对于n个数只需要n/30个字
节。这使得内存写的次数大大缩小,可明显的提升筛的速度。
这几天,我一直在利用休息时间编写筛法求素数的程序,目前的程序中包含了3个版本(算法)的程序,分别位于3个文
件siftPrime1.cpp,siftPrime3.cpp,siftPrime4.cpp,见楼下的附件。3个程序的功能完全相同,都是采用分段筛的方
法,可对4G以上范围内的数进行筛选。第一个程序几乎没有用到什么技巧,采用字节数组表示每个数是素数还是和数。第
二个程序采用了很多技巧,算法同 30# 楼给出的相同,只是现在的程序结构更加优化,测试更充分,解了 n>2^32不能
正常工作的bug。第三个程序是第二个程序的改进版,采用了一个模板,这个模板预先筛去了7,11,13,17的倍数,速度
提高了大约15%。
这三个程序的性能指标(以下数据均为在 PIV 2.6G,512K L2 cache下的测试数据,仅筛并统计素数个数不输出)
siftPrime1 siftPrime2 siftPrime3
1亿 0.78秒 0.172秒 0.125秒
10亿 8.25秒 1.86秒 1.547秒
100亿 92.78秒 21.7秒 18.4秒
源代码中函数接口说明:
下面是3个函数的接口,三个函数中仅名字不一样,函数接口完全一致,功能已完全一致.
UINT64 generalSift(UINT64 n,void *primeTab,int mode, UINT64 primeTabLimtCount);
UINT64 fastSift(UINT64 n,void *primeTab,int mode, UINT64 primeTabLimtCount);
UINT64 proSift(UINT64 n,void *primeTab,int mode, UINT64 primeTabLimtCount);
n表示筛的范围,如果n=1亿,将筛1-1亿之间(包括1亿)的所有素数.
primeTab 表示输出的素数表的地址,等于NULL 表示只统计个数,不输出.
mode: 表示要输出的素数表的格式,允许的取值有3个,4,8,30. 4表示输出到UINT32数组,每个素数占用4Byte,8表示输
出到 UINT64数组,每个素数占用8字节,30表示输出到素数bit表,n以内的素数暂用的空间为n/30字节,利用这个素数表可
迅速判断出n以内的任何一个数是否是素数.判断方法,将 primeTab 视为 BYTE*, 则primeTab【i】的bit0-bit7表示
i*30+(1,7,11,13,17,19,23,29)是否是和数,1:表示是合数, 0:表示是素数,值得注意的是这个表中并没有表示2,3,5这
三个素数的信息.bit数组的编码在上次那个附件的表示法和shines相反,这次改为和shines的一致.
primeTabLimtCount 表示PrimeTab的限制长度,如mode=4,则primeTab只能容纳 primeTabLimtCount * sizeof
(DWORD)个字节,多余的将不存储.如mode=8,则primeTab只能容纳 primeTabLimtCount * sizeof(UINT64)个字节,多余
的将不存储.mode=30,则primeTab只能容纳 primeTabLimtCount个字节,多余将不存储,如果primeTabLimtCount =0,则
只统计素数个数,不存储任何素数.
对这这个代码的输出部分进行修改,很容易改成搂住的另一个擂台所用的程序(极大素数间隔问题)
http://bbs.emath.ac.cn/thread-241-1-1.html
proSift可能是终极版本,其筛素数的速度很难有本质性的提高.
感谢shines所做的工作,他代码进行了改进,我的新版对统计素数个数时借鉴了他的一些算法. |
|