1. 程式人生 > >輸出指定範圍內的素數(質數)

輸出指定範圍內的素數(質數)

    這裡最近看到了一個方法Sieve of Eratosthenes的方法,突然覺得以前的方法太坑了,我以前都是直接使用窮舉法。

    先說一下我理解的原理:

        首先任何一個大於2的合數都等於一個素數乘以一個正整數,根據這個就可以開始推下面的方法。

    問題:求1-n的所有素數

    步驟:

        1、建立一個n大小的陣列A,將1標記為非素數,將2標記為素數,然後將3-n中所有的2的倍數標記為合數,同時將2賦值給K;

        2、判斷A中大於K的數是否已經全部被標記或者K等於n,如果是空跳到第4步;

        3、求得A中最小的未標記的數m,將m標記為素數,將B中所有m的倍數標記為合數,同時將m賦值給K,返回第2步;

        4、輸出陣列A中所有素數。

下面貼出程式碼:

#include <stdio.h>
#include <Windows.h>
#define UNLABELED 0     //未標記
#define PRINE 1         //素數
#define COMPOSITE 2     //合數
#define NOPRINE 3       //非素數

#define SIZE 100
int main()
{
	int i = 0;                        //i表示整數和對應的下標
	int j = 0;                        //j表示正要處理的素數j之前的已處理j之後的未處理
	int k = 0;                        //k表示正在處理的j的倍數從2開始到 j * k < SIZE
	int *p = NULL;                    //控制迴圈
	int a[SIZE + 1] = { 0 };          //下標表示整數內容判斷是否為素數
	for (p = a; p < a + SIZE; ++p) {  //初始化陣列全是UNLABELED
		*p = UNLABELED;
	}
	p = NULL;
	a[0] = a[1] = NOPRINE;            //設定前面兩個不是素數的數的狀態為NOPRINE
	i = 2;
	while (i < SIZE + 1) {
		//判斷是否未標記,找到下一個素數
		if (a[i] == UNLABELED) {
			j = i;
			a[i++] = PRINE;
		}
		else {
			//已經標記了繼續i++向下走
			i++;
			continue;
		}

		for (k = 2; j * k < SIZE; ++k) { //處理素數的倍數
			a[j * k] = COMPOSITE;
		}
	}
	for (p = a; p < a + SIZE; ++p) {           //打印出素數
		if (*p == PRINE) {
			printf("%8d", p - a);
		}
	}
	p = NULL;
	printf("\n");
	system("pause");
	return 0;
}

我把執行結果複製一遍吧,之前沒仔細看了,計算到一千,但是999沒有訪問到,所以1000的時候999打出來了,100的時候99打出來了,多謝指點了。

一個是1-100

這個是1-1000

-_-.