| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 8319 人关注过本帖, 2 人收藏
标题:这个程序运行了8个小时,求一亿以内的素数和超级素数.
只看楼主 加入收藏
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
/* 搜索一亿以内的素数以及“超级素数”*/

/* 下面的代码请在 TC 下编译连接
 tcc  thisfile.c <回车>
由于嵌入了汇编,运行速度大提高!
*/
void dummy( ){ _turboFloat(); } /*本行可躲开 TC 的一个瑕疵*/
#include<stdio.h>
#include<time.h>
#define SAVE_DISP {super[ns++]=x;printf("//第%ld个超级素数: %ld\n",ns,x);return(1);}

long ns=2,super[99]={2,3};/*超级素数*/

int Super(long x)/*假设x已经是素数*/
{
    long i;
    if(x<10)
        SAVE_DISP
    else if(x<20)
        return 0;
    else
    {
    for(i=ns-1;i>=0;i--)
        if(super[i]<=x/10)
        {
            if(super[i]==x/10)
               SAVE_DISP
            else
               return 0;
        }
    }
}

int main( void )
{
    long k,k2=1,kp=2,pmax,nd=10;
    long x,p[1230]={2,3},p2=3*3;
    for(x=5; x<100000000; x=x+2)
    {
        if(x==p2)
        {
            k2++;
            p2=p[k2]*p[k2];
            continue;
        }
        for(k=1; k<k2; k++)
        {
            /*if(x%p[k]==0)break;*/
            asm .386
            asm mov ax,k
            asm shl ax,2
            asm lea bx,p[0]
            asm add bx,ax
            asm mov eax,x
            asm mov edx,0
            asm div dword ptr [bx]
            asm and edx,edx
            asm jz  BREAK
        }
      BREAK:
        if(k>=k2)
        {
            if(kp<1230)p[kp]=x;
            kp++;
            if(kp%1000000==0||kp==nd)printf("//第%ld个素数=%ld\n",kp,x),nd*=10;
            pmax=x;
            Super(x);
        }
    }
    printf("//第%ld个素数=%ld\n",kp,pmax);
    printf("//运行耗时%.2f秒\n",clock()/18.2);
    return 0;
}
2010-12-14 19:21
budong998
Rank: 2
等 级:论坛游民
帖 子:25
专家分:15
注 册:2010-7-18
收藏
得分:0 
回复 31楼 yu_hua
编译时出错.
图片附件: 游客没有浏览图片的权限,请 登录注册
2010-12-16 21:30
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
回复 32楼 budong998

请在 TC 下编译连接,命令行是:
tcc  thisfile.c <回车>
由于嵌入了汇编,运行速度大提高!


[ 本帖最后由 yu_hua 于 2010-12-17 08:27 编辑 ]
2010-12-17 08:23
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
// 准筛法求一亿以内素数(VC 6.0)
// 下列代码速度极快、且内存开销小
// 2010-12-17(新鲜出炉)

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
long prime[1230][2]={2,2*2, 3,2*3};
void get_Ptable( void )
{   
    long n=5,p2=9,kr=1,kp=2,k;
    while(1)
    {   
        if(n==p2)
        {   
            kr++;
            p2=prime[kr][0]*prime[kr][0];
            continue;
        }   
        for(k=1; k<kr; k++)
        {   
            if(n % prime[k][0]==0)goto nadd2;
        }   
        prime[kp][0]=n;
        prime[kp][1]=n+n;
        if(++kp==1230)return;
        nadd2:
        n=n+2;
    }   
}   
int main( void )
{   
    #define BLOCK 100000 //请求分配的内存块字节数
    long n,k,np=0,BASE=0L,t1,t2;
    char *pp,*pw,*pend;
    t1 = clock(  );
    get_Ptable(  );
    pp=(char*)malloc(BLOCK*sizeof(char));
    if(pp==NULL)return -1;//失败
    do
    {
        pw=pp;
        pend=pp+BLOCK;
        do
        {
            *pw++=1;//预设都是素数
        }
        while(pw<pend);
        if(BASE==0)pp[0]=pp[1]=0; //0和1都不是素数
        for(k=0;k<1230-1;k++)//1万以内有1229个素数
        {    long ip=prime[k][0];
            long pi=prime[k][1]-BASE;
            for(n=pi;n<BLOCK;n+=ip)pp[n]=0;
            prime[k][1]=n+BASE;
        }   
        for(k=0;k<BLOCK;k++)if(pp[k])//如果你去掉下面两行的“//”那就显示9990万~1亿之间的素数
        {   //if(BASE==100000000-BLOCK)
            //printf("%-10ld",k+BASE); //“k+BASE”才是素数,“k”只是该素数在BLOCK中的偏移量
            np++;
        }
        BASE+=BLOCK;
    }
    while(BASE<100000000);
    t2 = clock( );
    printf("\n%0.1f sec\nTotal: %ld\n",(t2-t1)/1E3,np);
    free(pp); //在赛扬-333老爷机上耗时32.4秒
    return 0;
}   
2010-12-17 15:32
budong998
Rank: 2
等 级:论坛游民
帖 子:25
专家分:15
注 册:2010-7-18
收藏
得分:0 
回复 33楼 yu_hua
才学C语言,刚刚入一点门,连指针都还不会用.你说: TC 下编译连接
tcc  thisfile.c <回车>
我不懂要怎么样做.能不能麻烦你详细的讲讲,真诚的谢谢你这么多天来一直关注我的这个问题!
还有个请求:能把你的邮箱地址或QQ号或MSN给我吗?在你方便时,想给你学习.不懂的问题如果有你讲一讲,我想比我自己傻看几天资料来得快!
我的邮箱:budong998@
2010-12-17 17:37
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
// 准筛法求一千亿以内的素数(VC 6.0)
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#define PMAX 100000000000
#define NUMP 27294 //第27294个素数316241的平方已大于1000亿
long prime [NUMP]={2, 3};
long prime2[NUMP]={4, 6};
void set_Prime_table(void)
{   
    long n=5,p2=9, k,kr=1,kp=2;
    while(1)
    {   
        if(n==p2)
        {   
            kr++;
            p2=prime[kr]*prime[kr];
            continue;
        }   
        for(k=1; k<kr; k++)
        {   
            if(n % prime[k]==0)goto nadd2;
        }   
        prime[kp]=n;
        prime2[kp]=n+n;
        if(++kp==NUMP)break;
        nadd2:
        n=n+2;
    }   
    if((__int64)n*n<PMAX)abort( );
    return;
}   
int main(void)
{   
    #define BLOCK 0x8000 //VC6.0最佳值(Dell机), 在赛扬-333上0x4000为最佳
    static  char pp[BLOCK];
    __int64 BASE,np=0;
    long block,dn,k,nn,t2,t1=clock( );
    set_Prime_table( );
    for(np=BASE=0;BASE<PMAX;BASE+=BLOCK)
    {
        memset(pp,1,BLOCK);       //预设都是素数
        if(BASE==0)pp[0]=pp[1]=0; //0和1不是素数
        block = BLOCK;
        if(PMAX-BASE<BLOCK)block=(long)(PMAX-BASE);
        for(k=0; k<NUMP; k++)
        {   
            dn = prime [k];
            nn = prime2[k];
            while(nn<block)
            {   
                pp[nn]=0;
                nn=nn+dn;
            }
            prime2[k]=nn-BLOCK;
        }   
        for(k=0; k<block; k++)if(pp[k])
        {   
            if(BASE>=PMAX-BLOCK && k>block-1000)
            printf("%I64d\t",k+BASE);//显示最后1000个数中的素数
            np++;
        }
    }
    t2 = clock( );
    printf("\n%0.1f sec\nTotal: %I64d\n",(t2-t1)/1E3,np);
    return 0;
}
/*------------------------------------------------------------------------
BLOCK=0x4000(赛扬-333)
9999999001      9999999017      9999999019      9999999059      9999999067
9999999089      9999999103      9999999151      9999999157      9999999161
9999999169      9999999241      9999999253      9999999319      9999999337
9999999367      9999999371      9999999379      9999999479      9999999491
9999999511      9999999557      9999999619      9999999631      9999999661
9999999673      9999999679      9999999701      9999999703      9999999707
9999999727      9999999769      9999999781      9999999787      9999999817
9999999833      9999999851      9999999881      9999999929      9999999943
9999999967
618.4 sec
Total: 455052511 (100亿以内有这么多素数)

BLOCK=0x8000(戴尔)
99999999019, 99999999023, 99999999097, 99999999103, 99999999119, 99999999133,
99999999139, 99999999149, 99999999193, 99999999227, 99999999247, 99999999269,
99999999277, 99999999289, 99999999353, 99999999391, 99999999409, 99999999431,
99999999439, 99999999527, 99999999529, 99999999551, 99999999557, 99999999559,
99999999571, 99999999581, 99999999599, 99999999647, 99999999653, 99999999667,
99999999689, 99999999709, 99999999713, 99999999731, 99999999761, 99999999763,
99999999769, 99999999821, 99999999829, 99999999833, 99999999851, 99999999871,
99999999907, 99999999943, 99999999947, 99999999977
681.2 sec
Total: 4118054813 (1000亿以内有这么多素数)

---------------------------------------------------------------------------*/
一百 以内有        25个素数,它们分别是 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97。
一千 以内有       168个素数,最后几个是 907,911,919,929,937,941,947,953,967,971,977,983,991,997。
一万 以内有      1229个素数,最后几个是 9901,9907,9923,9929,9931,9941,9949,9967,9973。
十万 以内有      9592个素数,最后几个是 99901,99907,99923,99929,99961,99971,99989,99991。
一百万以内有     78498个素数,最后几个是 999907,999917,999931,999953,999959,999961,999979,999983。
一千万以内有    664579个素数,最后几个是 9999901,9999907,9999929,9999931,9999937,9999943,9999971,9999973,9999991。
一亿 以内有   5761455个素数,最后几个是 99999931,99999941,99999959,99999971,99999989。
十亿 以内有  50847534个素数,最后几个是 999999929,999999937。
一百亿以内有 455052511个素数,最后几个是 9999999929,9999999943,9999999967。
一千亿以内有4118054813个素数,最后1000个连续数中有46个素数:
99999999019, 99999999023, 99999999097, 99999999103, 99999999119, 99999999133, 99999999139, 99999999149,
99999999193, 99999999227, 99999999247, 99999999269, 99999999277, 99999999289, 99999999353, 99999999391,
99999999409, 99999999431, 99999999439, 99999999527, 99999999529, 99999999551, 99999999557, 99999999559,
99999999571, 99999999581, 99999999599, 99999999647, 99999999653, 99999999667, 99999999689, 99999999709,
99999999713, 99999999731, 99999999761, 99999999763, 99999999769, 99999999821, 99999999829, 99999999833,
99999999851, 99999999871, 99999999907, 99999999943, 99999999947, 99999999977。


[ 本帖最后由 yu_hua 于 2010-12-18 11:06 编辑 ]
2010-12-17 21:02
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
/* 准筛法求一万亿以内素数(VC 6.0)*/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>

#define PMAX 1000000000000
#define NUMP 78500
long prime [NUMP]={2, 3};
long prime2[NUMP]={4, 6};

void set_Prime_table(void)
{   
    long n=5,p2=9, k,kr=1,kp=2;
    while(1)
    {   
        if(n==p2)
        {   
            kr++;
            p2=prime[kr]*prime[kr];
            continue;
        }   
        for(k=1; k<kr; k++)
        {   
            if(n % prime[k]==0)goto nadd2;
        }   
        prime[kp]=n;
        prime2[kp]=n+n;
        if(++kp==NUMP)break;
        nadd2:
        n=n+2;
    }   
    if((__int64)n*n<PMAX)abort( );
    return;
}   

int main(void)
{   
    #define BLOCK 0x8000 //VC6.0最佳值(Dell机), 在赛扬-333上0x4000为最佳
    static  char pp[BLOCK];
    __int64 BASE,np=0;
    long block,dn,k,nn,t2,t1=clock( );
    set_Prime_table( );
    for(np=BASE=0;BASE<PMAX;BASE+=BLOCK)
    {
        memset(pp,1,BLOCK);       //预设都是素数
        if(BASE==0)pp[0]=pp[1]=0; //0和1不是素数
        block = BLOCK;
        if(PMAX-BASE<BLOCK)block=(long)(PMAX-BASE);
        for(k=0; k<NUMP; k++)
        {   
            dn = prime [k];
            nn = prime2[k];
            while(nn<block)
            {   
                pp[nn]=0;
                nn=nn+dn;
            }
            prime2[k]=nn-BLOCK;
        }   
        for(k=0; k<block; k++)if(pp[k])
        {   
            if(BASE>=PMAX-BLOCK && k>block-1000)
            printf("%I64d\t",k+BASE);//显示最后1000个数中的素数
            np++;
        }
    }
    t2 = clock( );
    printf("\n%0.1f sec\nTotal: %I64d\n",(t2-t1)/1E3,np);
    return 0;
}
/*----------------------------------------------------------------------------------------------------------
一万亿以内有37607912018个素数,最后1000个连续数中有38个素数,它们是
999999999091    999999999101    999999999133    999999999143    999999999161    999999999247    999999999253        
999999999269    999999999277    999999999287    999999999293    999999999301    999999999331    999999999359
999999999391    999999999457    999999999497    999999999517    999999999529    999999999571    999999999577   
999999999589    999999999599    999999999611    999999999617    999999999673    999999999697    999999999707   
999999999767    999999999847    999999999857    999999999863    999999999877    999999999899    999999999937   
999999999959    999999999961    999999999989    耗时13137.3秒(戴尔)
------------------------------------------------------------------------------------------------------------*/
2010-12-18 16:59
creativewang
Rank: 1
来 自:changchun
等 级:新手上路
帖 子:8
专家分:2
注 册:2010-1-12
收藏
得分:0 
效率有点低...

To be the best!
2011-06-16 21:20
快速回复:这个程序运行了8个小时,求一亿以内的素数和超级素数.
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017444 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved