alg : 找1 to N的质数(筛法)

算法思路参考 : 

质数筛法 : http://blog.csdn.net/program_think/article/details/7032600


在驱动层实现了一个质数筛法.

/// @file           Function.h
/// @brief          功能的实现

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

#include <ntddk.h>

#ifndef BYTE
#define BYTE unsigned char
#endif

#define BYTE_BITS           8
#define BYTE_BITS_MASK(x)   (1 << x)

/// @fn         PrintPerime
/// @brief      打印 0~nMax 之间的质数, 用筛法实现
void PrintPerime(size_t nMax);

/// @fn         MakePerime
/// @brief      制作质数Buffer
void MakePerime(size_t nMax, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         ShowPerime
/// @brief      打印质数Buffer
void ShowPerime(size_t nMax, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         IsNumberPerime
/// @brief      判断一个数是否是质数
BOOLEAN IsNumberPerime(size_t nNumber, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         IsNumberPerimeFlag
/// @brief      判断一个数是否是质数标记
BOOLEAN IsNumberPerimeFlag(size_t nNumber, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         SetMultipleValue
/// @brief      设置nNumber倍数的值为bVal
void SetMultipleValue(size_t nNumber, BOOLEAN bVal, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         SetNumberValue
/// @brief      设置nNumber的值为bVal
void SetNumberValue(size_t nNumber, BOOLEAN bVal, BYTE * pcPerime, size_t nBufLenPerime);

/// @fn         IsNumberNeedSkip
/// @brief      是否为需要逃过判断的数, 0, 1, 不需要判断质数
BOOLEAN IsNumberNeedSkip(size_t nNumber);

#endif

/// @file           Function.c
/// @brief          功能的实现

#include "Function.h"

void PrintPerime(size_t nMax)
{
    /// 用1Bit代表一个数, 1Byte代表8个数, 用N Bytes 代表 0~nMax
    size_t  nByteNumber =   (nMax - nMax % 8) / 8 + ((0 == (nMax % 8)) ? 0 : 1);
    BYTE *  pcPerime    =   ExAllocatePoolWithTag(PagedPool, nByteNumber, 'PRIM');

    if (NULL == pcPerime)
    {
        DbgPrint("NULL == pcPerime\r\n");
        return;
    }

    memset(pcPerime, 0xff, nByteNumber);   ///< 假设所有的数都是质数

    /// 设置0, 1不是素数为初始条件
    SetNumberValue(0, FALSE, pcPerime, nByteNumber);
    SetNumberValue(1, FALSE, pcPerime, nByteNumber);

    MakePerime(nMax, pcPerime, nByteNumber);
    ShowPerime(nMax, pcPerime, nByteNumber);

    ExFreePool(pcPerime);
}

void MakePerime(size_t nMax, BYTE * pcPerime, size_t nBufLenPerime)
{
    /// pcPerime 给定的值都是质数标记

    size_t  nLoop       =   0;  ///< Buffer的循环
    size_t  nLoopByte   =   0;  ///< Buffer中字节的循环
    size_t  nNumberCur  =   0;  ///< 当前位代表的数字, 如果是质数, 直接打印出来

    for (nLoop = 0; nLoop <nBufLenPerime; nLoop++)
    {
        for (nLoopByte = 0; nLoopByte < BYTE_BITS; nLoopByte++)
        {
            if (!IsNumberPerime(nNumberCur, pcPerime, nBufLenPerime))
                SetNumberValue(nNumberCur, FALSE, pcPerime, nBufLenPerime);

            SetMultipleValue(nNumberCur, FALSE, pcPerime, nBufLenPerime);   ///< 每个数的倍数都不是质数
            if (nNumberCur++ >= nMax)
                break;
        }
    }
}

BOOLEAN IsNumberNeedSkip(size_t nNumber)
{
    return ((0 == nNumber) || (1 == nNumber));
}

void SetNumberValue(size_t nNumber, BOOLEAN bVal, BYTE * pcPerime, size_t nBufLenPerime)
{
    size_t  nBytesPosBit    =   nNumber % BYTE_BITS;    ///< 在该字节的位(位置)
    size_t  nBytesPos       =   (nNumber - nBytesPosBit) / BYTE_BITS;   ///< 在Buffer中的字节位置

    if (bVal)
        *(pcPerime + nBytesPos) |= BYTE_BITS_MASK(nBytesPosBit);
    else
        *(pcPerime + nBytesPos) &= ~(BYTE_BITS_MASK(nBytesPosBit));
}

void SetMultipleValue(size_t nNumber, BOOLEAN bVal, BYTE * pcPerime, size_t nBufLenPerime)
{
    size_t  nLoop           =   0;  ///< Buffer的循环
    size_t  nLoopByte       =   0;  ///< Buffer中字节的循环
    size_t  nNumberCur      =   0;  ///< 当前位代表的数字, 如果是质数, 直接打印出来
    size_t  nBytesPosBit    =   0;  ///< 在该字节的位(位置)
    size_t  nBytesPos       =   0;  ///< 在Buffer中的字节位置

    if (IsNumberNeedSkip(nNumber))
        return;

    nBytesPosBit    =   nNumber % BYTE_BITS;
    nBytesPos       =   (nNumber - nBytesPosBit) / BYTE_BITS;
    nNumberCur      =   nBytesPos * BYTE_BITS + nBytesPosBit;
    for (nLoop = nBytesPos; nLoop <nBufLenPerime; nLoop++)
    {
        for (nLoopByte = nBytesPosBit; nLoopByte < BYTE_BITS; nLoopByte++)
        {
            if (nNumberCur <= nNumber)  ///< 不包括设置nNumber
            {
                nNumberCur++;
                continue;
            }

            if (0 == (nNumberCur % nNumber))
            {
                /// 当前数能被nNumber整除, 是nNumber的倍数
                SetNumberValue(nNumberCur, bVal, pcPerime, nBufLenPerime);
            }

            nNumberCur++;
        }

        nBytesPosBit = 0;   ///< 除了第一次使用, 都是从0开始
    }
}

BOOLEAN IsNumberPerimeFlag(size_t nNumber, BYTE * pcPerime, size_t nBufLenPerime)
{
    size_t  nBytesPosBit    =   nNumber % BYTE_BITS;    ///< 在该字节的位(位置)
    size_t  nBytesPos       =   (nNumber - nBytesPosBit) / BYTE_BITS;   ///< 在Buffer中的字节位置

    if (IsNumberNeedSkip(nNumber))
        return FALSE;

    return (0 == (*(pcPerime + nBytesPos) & BYTE_BITS_MASK(nBytesPosBit))) ? FALSE : TRUE;
}

BOOLEAN IsNumberPerime(size_t nNumber, BYTE * pcPerime, size_t nBufLenPerime)
{
    BOOLEAN bIsPerime       =   TRUE;
    size_t  nPos            =   0;
    size_t  nPosMax         =   0;
    size_t  nBytesPosBit    =   nNumber % BYTE_BITS;    ///< 在该字节的位(位置)
    size_t  nBytesPos       =   (nNumber - nBytesPosBit) / BYTE_BITS;   ///< 在Buffer中的字节位置

    if (!IsNumberPerimeFlag(nNumber, pcPerime, nBufLenPerime))
        return FALSE;   ///< 如果已经被前面的操作置为"非质数", 直接返回"非质数"

    /// 在nNumber之前的数都已经正确的标记了是否为质数
    /// 只有一半以下的数, 有可能被整除
    nPosMax = (size_t)((nNumber - (nNumber % 2)) / 2);
    for (nPos = 2; nPos <= nPosMax; nPos++)
    {
        if  (!IsNumberPerimeFlag(nPos, pcPerime, nBufLenPerime))    ///< 不是质数不用整除
            continue;   

        if ((nNumber % nPos) == 0)
        {
            bIsPerime = FALSE;
            break;
        }
    }

    return bIsPerime;
}

void ShowPerime(size_t nMax, BYTE * pcPerime, size_t nBufLenPerime)
{
    size_t  nLoop       =   0;  ///< Buffer的循环
    size_t  nLoopByte   =   0;  ///< Buffer中字节的循环
    size_t  nNumberCur  =   0;  ///< 当前位代表的数字, 如果是质数, 直接打印出来

    for (nLoop = 0; nLoop <nBufLenPerime; nLoop++)
    {
        for (nLoopByte = 0; nLoopByte < BYTE_BITS; nLoopByte++)
        {
            if ((*(pcPerime + nLoop) & BYTE_BITS_MASK(nLoopByte)) > 0)
                DbgPrint("%d\r\n", nNumberCur);

            if (nNumberCur++ >= nMax)
                break;
        }
    }
}

调用 PrintPerime

/// @file           sys.c
/// @brief          驱动主程序

#include <ntddk.h>
#include "Function.h"

#define MODULE_NAME         L"DrvDemo"
#define DRIVER_NAME         MODULE_NAME L".sys"
#define DEVICE_NAME_GLOBAL  L"\\\\.\\" MODULE_NAME
#define DEVICE_NAME         L"\\device\\" MODULE_NAME
#define LINK_NAME           L"\\dosDevices\\" MODULE_NAME

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, 
                     IN PUNICODE_STRING pRegPath)
{
    size_t          nIndex          =   0;

    /// 找出40000以内的素数(筛法)
    size_t          nReqPerimeMax   =   40000;   ///< 求质数的范围上限

    NTSTATUS        ntStatus = STATUS_SUCCESS;
    PDEVICE_OBJECT  pDeviceObject = NULL;

    UNICODE_STRING  ustrDeviceName = {0};
    UNICODE_STRING  ustrLinkName = {0};

    DbgPrint(">> DriverEntry\r\n");

    RtlInitUnicodeString(&ustrDeviceName, DEVICE_NAME);
    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);

    ntStatus = IoCreateDevice(
        pDriverObject, 
        0, 
        &ustrDeviceName, 
        FILE_DEVICE_UNKNOWN, 
        0, 
        FALSE, 
        &pDeviceObject);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("<< DriverEntry : error IoCreateDevice\r\n");
        return ntStatus;
    }

    pDeviceObject->Flags |= DO_BUFFERED_IO;
    ntStatus = IoCreateSymbolicLink(
        &ustrLinkName, 
        &ustrDeviceName);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("<< DriverEntry : error IoDeleteDevice\r\n");
        IoDeleteDevice(pDeviceObject);
        return ntStatus;
    }

    for(nIndex = 0; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++)
    {
        pDriverObject->MajorFunction[nIndex] = DispatchCommon;
    }

    pDriverObject->DriverUnload = DriverUnload;

    
    PrintPerime(nReqPerimeMax); /// 找出nReqPerimeMax以内的素数(筛法)

    DbgPrint("<< DriverEntry\r\n");

    return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    UNICODE_STRING ustrLinkName = {0};

    DbgPrint(">> DriverUnload\r\n");

    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
    IoDeleteDevice(pDriverObject->DeviceObject);
    IoDeleteSymbolicLink(&ustrLinkName);

    DbgPrint("<< DriverUnload\r\n");
}

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = STATUS_SUCCESS;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

实验截图:

alg : 找1 to N的质数(筛法)_第1张图片

alg : 找1 to N的质数(筛法)_第2张图片











你可能感兴趣的:(alg : 找1 to N的质数(筛法))