算法——质数处理

来源:互联网 发布:算法的乐趣 pdf 编辑:程序博客网 时间:2024/06/05 17:35

质数的相关处理


1. 判断一个数是否是素数

只能被1和本身整除的自然数就是素数
如何判断一个数是否是素数
比较合适的方式就是不断的除余

#include"stdio.h"#include"math.h"int main( int argc, char* argv[]){    int i,k,m;    while( scanf("%d",&i) && i != 0 )    {        k=sqrt(i);  //判别i是否为素数,只需使2~根号i之间的每一个整数去除        for(m=2;m<=k;m++)        {            if(i%m==0)                break;        }        if(m>k)            printf("%d是素数 ",i);        else            printf("%d不是素数",i);    }    return 0;}

运行结果:
这里写图片描述


2. 求一个范围数是否是素数

比较常规的是将上面的逻辑封装成一个函数,然后循环遍历判断每一个数

另外一种思路去处理有限范围内的素数查找
假如求1到4096之间的所有素数:

#include "stdafx.h"#include "stdio.h"#define SIZE 4096class CPrimeNum{public:    CPrimeNum( int n )    {        m_Attr[0] = 1;  // 1不是质数        for( int i = 1; i < n; i++ )        {            m_Attr[i] = 0;           }        int j = 0;        for( ; i < SIZE; i++ )        {            j++;            if( j == n )            {                m_Attr[i] = 1;                j = 0;            }            else            {                m_Attr[i] = 0;            }        }    }    void MaskWith( CPrimeNum m )    {        for( int i = 0; i < SIZE; i++ )        {            m_Attr[i] = m_Attr[i] | m.m_Attr[i];        }    }    int m_Attr[SIZE];};CPrimeNum glbPrimeNum(2);int GetNextPrimeNum( int Current ){    for( int i = Current; i < SIZE; i++ )    {        if( glbPrimeNum.m_Attr[i] == 0 )            return i+1;    }    return 0;}int main(){    int Current = 2;    int Count = 1;    while( Current )    {        printf( "%d ", Current );        if( Count == 15 )        {            printf("\n");            Count = 0;        }        Current = GetNextPrimeNum( Current );        Count++;        glbPrimeNum.MaskWith(Current);    }    return 0;}

运行结果:
这里写图片描述
当然是不会有错误的啦,而且还比较高效,但是限于如果用的是数组成员变量,本身可能就无法获取太大范围的,所以可以考虑改良成 new 操作符去进行申请内存。

3. 求范围内的质数的优化型

#include "stdio.h"#include <string.h>class CPrimeNum{public:    CPrimeNum( int MaxRange )    {        m_nMaxRange = MaxRange;        m_pAttr = new char[MaxRange];    }    ~CPrimeNum()    {        if( m_pAttr )            delete []m_pAttr;    }private:    void MaskWithPrimeNum( int m )    {        int j = 0;        for( int i = m; i < m_nMaxRange; i++ )        {            j++;            if( j == m )            {                m_pAttr[i] = 1;                j = 0;            }        }    }    void InitAttr()    {        memset( m_pAttr, 0, sizeof(char)*m_nMaxRange );        int j = 0;        for( int i = 2; i < m_nMaxRange; i++ )        {            j++;            if( j == 2 )            {                m_pAttr[i] = 1;                j = 0;            }        }    }    int GetNextPrimeNum( int m )    {        for( int i = m; i < m_nMaxRange; i++ )        {            if( m_pAttr[i] == 0 )                return i + 1;        }        return 0;    }public:    void PrintAll()    {        InitAttr();        int Current = 2;        int Count = 1;        while( Current )        {            printf( "%d ", Current );            if( Count == 15 )            {                printf("\n");                Count = 0;            }            Current = GetNextPrimeNum( Current );            Count++;            MaskWithPrimeNum(Current);        }    }    char* m_pAttr;    int   m_nMaxRange;};void main(){    CPrimeNum PrimeNum(10000);    PrimeNum.PrintAll();}

运行结果:
这里写图片描述
刚好和上述可以相互应证

我们修改main函数来测试下效率
设置断点,并运行:
这里写图片描述
花了84.657秒计算出了100万以内的所有质数,速度上貌似有点慢,总体还是前面的遍历赋值的时候的消耗比较多。

正在寻求更加有效的方式….

4.用遍历判断方式去查找所有质数

#include "stdafx.h"#include"stdio.h"#include"math.h"#include <windows.h>bool bPrime( int g ){    int i,k,m;    k = sqrt(g);    for(m=2;m<=k;m++)    {        if(i%m==0)            break;    }    if(m>k)        return true;    else        return false;}int main( int argc, char* argv[]){    long t1 = GetTickCount();    for( int i = 1; i < 1000000; i++ )    {        bPrime(i);    }    long t2 = GetTickCount();    long t = t2 - t1;    return 0;}

最后结果:
t = 32 毫秒 (哦,myGod, 肯定是我打开的方式不对)

0 0
原创粉丝点击