Chinaunix首页 | 论坛 | 博客
  • 博客访问: 29158
  • 博文数量: 16
  • 博客积分: 600
  • 博客等级: 上士
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-21 13:21
文章分类

全部博文(16)

文章存档

2011年(1)

2008年(15)

我的朋友
最近访客

分类: C/C++

2008-03-10 22:09:15

#include<iostream>
#include<bitset>//但是它是没有要求的,这是对空间要求比较高的情况下用的位操作
#include<time.h>//它的使用是在用了using namespace std后,还要加上.h,同样的对于stdlib.h,math.h也是如此
#include<stdlib.h>
#include<math.h>
#define N 100000000
using namespace std;
int sieveSTL()
{
    //cout<<"请输入要查找的范围如:1~x"<<endl;
    //unsigned int n;
    //cin>>n;
    bitset<N>& p=*new bitset<N>;//没有实现动态的输入吗?
    p.set();//将所有的位都置于1;
    int num=N-2;//1,0根本没有判断到
    int r=sqrt(N);
    for(int i=2;i<=r;i++)//1,0根本没有判断到,看起点就知道
    
        if(p.test(i))//取第i位的值是0还是1
            for(int j=i*i;j<p.size();j+=i)//这里j+=i即j=i*(i+1);
                if(p.test(j) && num--) p.reset(j);//与set的含义相反,同这句(p[j/32] &(1<<j%32) && num--)相同\
                        delete[] &p;//这样子写就必须是地址常量
                        return num;
}
int sieve()
{
    cout<<"请输入要查找的范围如:1~x(这个范围不包括x,请注意)"<<endl;
    int n;
    cin>>n;
    int t=n/8;
     unsigned int* p;
    if(!(n%8))
    {if(n<8)
        t=4;
     else p=(unsigned int*) malloc(t);
    }
    else
    { t++;p=(unsigned int*) malloc(t);}
    memset(p,255,t);//将t个字节初始化为全1,这里只能对字节操作(是它的单位)
    int num=n-2;//这里要知道,我们对num的操作,是根据这个位是不是非素数,但有一个数据是判断不到的,就是1,它是从2开始的
    int f=sqrt(n);
    for(int i=2;i<=f;i++)
        if(p[i/32] & (1<<i%32))//1左移i%32位,这里有为什么要左移的问题,因为我们这个p相当于多个整型数据末是0,并不是起点因为这里用的是取余的操作
            //它既兼顾了1这个数的作用,同时又有了一个移位的操作
            //这个操作还有一重意思,就是如果说这个判断是假的,那么意味着,它的所有的倍数都置0了,它可能是由于它的因子将它置的原因
            for(int j=i*i;j<n;j+=i)//如果说有一个数n,它有因子,那么我们对它开方得其根,那么它的因子一定会小于这个算术根,即因子的平方会小于n
                if(p[j/32] &(1<<j%32) && num--)//位操作要高于逻辑操作,这句话的含义是,p[j/32] &(1<<j%32)是1,而本身j这个元素不是素数,要去掉的,这个结果是1
                     //表示这个非素数,以前并没有发现,如果是0,表示以前发现了,那么那时的num就已经自减了,如今不用再减了.
                p[j/32] &=~(1<<j%32);//那么当这个取i是这个因子的值时,就不会漏了对这个n的判断了
            free(p);
            return num;
}
int main()
{
    clock_t start=clock();
    cout<<sieve();
    cout<<" "<<(clock()-start)/CLK_TCK<<endl;
    return 0;
}
//这里有一人些编程的技巧就是:对素数的判断操作和一个统计的操作问题,如果我们将两个分开操作的话,那么又要多循环一遍,还不如边判断时就统计它
//这里恰好用了一个倒减的方式,刚好符合了,我们对素数的判断恰好看它是不是非素数,统一起来了.
//若是int num=n-1;这里要知道,我们对num的操作,是根据这个位是不是非素数,但有一个数据是判断不到的,就是1,它是从2开始的,而此时,我们说这个n的最后值是不可能达到的
//这里的内存分配是这样的,我们的位是从0~n/32-1,这对我们的最后的条件判断是j<n,还是j<=n有影响,因为p[j/32]是不存在的,写成j<=n;则最后会超出申请的空间的范围

阅读(914) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~