ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • KMS04 : C++ 소수탐색 프로그램 Ver3 (source)
    Program_Light 2021. 3. 20. 13:00

     

    사진출처 © florianklauer, 출처 Unsplash

    안녕하세요 tomskang입니다. 오늘은 지난번에 만든 소수 탐색기를 업그레이드 시켜보았는데요

    이번에 확실하게 프로그래밍을 각잡고 해서, 최적화되었다 할 수는 없지만, 여러 방면으로 지금까지 나온 소수탐색기 중 가장 혁신적인 성능을 가졌습니다.

     

    <지난번 코드>https://blog.naver.com/tomskang/221714771632

     

    [C++]소수탐색 프로그램 Ver2(source)

    ​이번에 여러모로 바빠서 프로그래밍을 못했었다. 그래서 오랜만에 연습도 할 겸 지난번에 만든 소수탐색 ...

    blog.naver.com

    <목차>

    1.    바뀐점
    2.       소스
    3. 함수설명
    4.       실행

     

    바뀐점은 위와 같습니다. 대부분의 블로그에서는 보지 못했던 새로운 기능을 추가하고자 생각하였고, 그 결과 "저장"이라는 새로운 기능이 생겨났습니다.


    [소스]

    (425line)

    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <windows.h>
    #include <ctime>
    
    using namespace std;
    
    enum { standard, list };
    
    typedef long long pd;
    
    #define TRUE	1
    #define FALSE	0
    
    #define FILE_READ_N		500000 //한번에 .bin에서 소수 데이터를 읽는 양
    #define PRINT_PRIME		500 //소수 PRINT_PRIME개당 하나를 출력
    #define FILE_WRITE_N	2 * PRINT_PRIME //한번에 .bin에 소수 데이터를 쓰는 양
    #define TEST_NUM		10000 //소수 TEST_NUM개당 1개씩 소수인지 검사함
    
    #define LINE_PER_PRIME	8 // decode시 한 줄당 출력하는 소수의 수 (must : mode = stndard)
    
    #define MODE			standard // DECODE 출력모드[standard/list]
    
    #define MAX(x, y)	(((x) > (y)) ? (x) : (y))
    #define MIN(x, y)	(((x) < (y)) ? (x) : (y))
    
    bool C;
    
    enum { BLACK = 0, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, PINK, YELLOW, WHITE };
    
    inline void textcolor(int text, int back) {
    	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), text | (back << 4));
    }
    // void textcolor(alpa, beta) 출처| https://andrew0409.tistory.com/162
    
    //ab
    pd f(pd N) {
    	if (C) {
    		N += 2;
    		C = FALSE;
    	}
    	else {
    		N += 4;
    		C = TRUE;
    	}
    	return N;
    }
    
    void delay(double sec) {
    	clock_t ct;
    	ct = clock();
    	while (ct + CLK_TCK * sec > clock());
    }
    
    bool ISPRIME(pd N) {
    	for (pd i = 2; i < sqrtl((long double)N); i++) {
    		if (!fmodl(N, i))
    			return FALSE;
    	}
    	return TRUE;
    }
    
    int SETUP(void);
    int KMS04main(void);
    int FtoT(void); // F(.bin) to Text
    void KMS04refresh(void);
    
    int main(void) {
    	char c;
    	system("color 0f");
    	do {
    		cout << "KMS05 type? " << endl;
    		cout << "[SETUP | S]  " << "[KMS05 | KorM]  " << "[DECODE TO TEXT | D]  " << endl << endl;
    		textcolor(LIGHTCYAN, BLACK);
    		cout << "-> ";
    		cin >> c;
    		if (('a' <= c) && (c <= 'z'))
    			c += 'A' - 'a';
    
    		switch (c) {
    		case 'S':
    			return SETUP();
    			break;
    		case 'K':
    		case 'M':
    			return KMS04main();
    			break;
    		case 'D':
    			return FtoT();
    			break;
    		}
    
    	} while (TRUE);
    
    	return 0;
    }
    
    // setup main
    int SETUP(void) {
    	// ********** setup ********** //
    	FILE* fp;
    	pd arr[3] = { 2, 3, 5 };
    	long size;
    	char c;
    
    	system("cls");
    
    	fopen_s(&fp, "pdata.bin", "rb");
    	if (fp != NULL) {
    		fseek(fp, 0, SEEK_END);
    		size = ftell(fp);
    		fclose(fp);
    
    
    		if (size > 20) {
    			cout << size << " data will disappear" << endl;
    			cout << "Is it okay ? " << endl << endl;
    
    			cout << "[YES | Y]  [NO | N]" << endl << "-> ";
    			cin >> c;
    
    			if ((c == 'N') || (c == 'n'))
    				return 0;
    		}
    	}
    
    	system("cls");
    	delay(0.5);
    	fopen_s(&fp, "pdata.bin", "wb");
    	if (fp == NULL) {
    		cout << "file(pdata.bin) open(wb) error" << endl;
    		return 0;
    	}
    	fwrite((void*)arr, sizeof(pd), 3, fp);
    	cout << "setup seccess" << endl;
    	return 0;
    }
    
    void KMS04refresh(void) {
    	vector<pd> prime;
    	pd num = 0;
    	bool con = FALSE;
    
    	FILE* fpr;
    	FILE* wpr;
    	pd* file_arr = new pd[MAX(FILE_READ_N + 1, FILE_WRITE_N + 1)];
    	int readCnt1;
    	int readCnt2;
    	long long K;
    
    	textcolor(BLACK, WHITE);
    
    	// ********** reading file ********** //
    
    	fopen_s(&fpr, "ppdata.bin", "rb");
    	if (fpr == 0) {
    		cout << "file(pdata.bin) open(rb) error" << endl;
    		return;
    	}
    
    	for (int forcnt = 0; TRUE; ) {
    		readCnt1 = fread((void*)file_arr, sizeof(pd), FILE_READ_N, fpr);
    		if (readCnt1 < FILE_READ_N) {
    			if (feof(fpr) != 0) {
    				for (int i = 0; i < readCnt1; i++) {
    					if (file_arr[i] <= 1)
    						continue;
    					prime.push_back(file_arr[i]);
    				}
    
    				delay(1);
    				system("cls");
    				cout << "file read success" << endl;
    				cout << "starting KMS05..." << endl;
    				delay(1.5);
    				system("cls");
    				delay(0.5);
    
    			}
    			else {
    				cout << "file read failed" << endl;
    				return;
    			}
    			break;
    		}
    		for (int i = 0; i < FILE_READ_N + 1; i++) {
    			if (file_arr[i] <= 1)
    				continue;
    			prime.push_back(file_arr[i]);
    		}
    		forcnt++;
    		if (!(forcnt % 10))
    			cout << "read " << forcnt * FILE_READ_N << "elements" << endl;
    	}
    
    	fclose(fpr);
    	fopen_s(&wpr, "pdata.bin", "wb");
    	K = prime.size();
    	readCnt1 = 0;
    	for (int i = 0; i < K; i++) {
    		file_arr[readCnt1++] = prime[i];
    		if (readCnt1 >= FILE_WRITE_N) {
    			fwrite((void*)file_arr, sizeof(pd), FILE_WRITE_N, wpr);
    			readCnt1 = 0;
    		}
    	}
    
    	fclose(wpr);
    	return;
    }
    
    //main part
    int KMS04main(void) {
    	vector<pd> prime;
    	pd num;
    	bool isPrime = TRUE;
    	long file_size;
    
    	FILE* fpr;
    	pd* file_arr = new pd[MAX(FILE_READ_N + 1, FILE_WRITE_N + 1)];
    	int readCnt1, readCnt2;
    
    	textcolor(GREEN, BLACK);
    	system("cls");
    
    	// ********** reading file ********** //
    
    	fopen_s(&fpr, "pdata.bin", "rb");
    	if (fpr == 0) {
    		cout << "file(pdata.bin) open(rb) error" << endl;
    		return 0;
    	}
    
    	// get .bin's file size
    	fseek(fpr, 0, SEEK_END);
    	file_size = ftell(fpr) / sizeof(pd);
    	fseek(fpr, 0, SEEK_SET);
    
    	cout << "if pdata.bin file was too big, percent indicator won't working" << endl;
    	for (int forcnt = 0; TRUE; ) {
    		readCnt1 = fread((void*)file_arr, sizeof(pd), FILE_READ_N, fpr);
    		if (readCnt1 < FILE_READ_N) {
    			if (feof(fpr) != 0) { for (int i = 0; i < readCnt1; i++) { prime.push_back(file_arr[i]); } }
    
    			delay(1);
    			system("cls");
    			cout << "file read success" << endl;
    			cout << "starting KMS05..." << endl;
    			delay(1.5);
    			system("cls");
    			delay(0.5);
    			break;
    		}
    		for (int i = 0; i < FILE_READ_N + 1; i++) {
    			if (file_arr[i] <= 1)
    				continue;
    			prime.push_back(file_arr[i]);
    		}
    		forcnt++;
    		if (!(forcnt % 10)) {
    			cout << "read " << forcnt * FILE_READ_N << "elements\t" << (long)(prime.size() * 100 / file_size) << "percent complete" << endl;
    		}
    	
    	}
    	fclose(fpr);
    
    	// ********** cuclulating ********** //
    
    	fopen_s(&fpr, "pdata.bin", "ab");
    	textcolor(WHITE, BLACK);
    	if (fpr == 0) {
    		cout << "file(pdata.bin) open(ab) error. maybe file doesn't exist" << endl;
    		return 0;
    	}
    
    	readCnt1 = 0; // valueable for fwrite
    	readCnt2 = 4; // valueable for print, test
    
    	C = (fmodl(prime.at(prime.size() - 1), 6.0) == 1) ? FALSE : TRUE;
    	for (num = f(prime.at((int)prime.size() - 1)); TRUE; num = f(num)) {
    		for (int i = 2; ((sqrtl(num)) >= prime[i]); i++) {
    			if (!(fmodl(num, prime[i]))) {
    				isPrime = FALSE;
    				break;
    			}
    		}
    
    		if (!isPrime) { // is num isn't prime -> continue
    			isPrime = TRUE;
    			continue;
    		}
    
    		prime.push_back(num);
    		if (readCnt2 >= PRINT_PRIME) {
    			cout << prime.size() << "th prime : " << num;
    			cout << "        " << num / 1000 << "K" << "\t" << num / 1000000 << "M" << endl; // print prime
    			readCnt2 = 0;
    		}
    
    		file_arr[readCnt1++] = num;
    		readCnt2++;
    
    		if (!(prime.size() % TEST_NUM)) {
    			if (ISPRIME(num)) {
    				textcolor(GREEN, BLACK);
    				cout << "[EXAMINATION : seccessful]" << endl;
    				textcolor(WHITE, BLACK);
    			}
    			else {
    				textcolor(LIGHTRED, WHITE);
    				cout << "ERROR : founded prime was not prime" << endl;
    				cout << "close KMS04" << endl;
    				cout << "[This programm Recommend setup this program]" << endl << endl;
    				textcolor(WHITE, BLACK);
    				system("pause");
    				break;
    			}
    		}
    		if (readCnt1 >= FILE_WRITE_N) {
    			fwrite((void*)file_arr, sizeof(pd), FILE_WRITE_N, fpr);
    			readCnt1 = 0;
    		}
    	}
    
    	fclose(fpr);
    	delay(1);
    	system("cls");
    	cout << "KMS04 closing..." << endl;
    	delay(2);
    	system("cls");
    
    	return 0;
    }
    
    #define FILE_NUM	100000000 //끊는 단위 [10^N이여야 함]
    #define FILE_N_READ	"억" //FILE_NUM 읽는 법
    
    int FtoT(void) {
    	FILE* BIN;
    	FILE* TXT;
    
    	pd arr[6];
    	int readCnt;
    
    	//char TXTname[50] = { NULL, };
    
    	int count = 0;
    	int fnameCnt = 0;
    
    	const char* ending = "\n \n MADE BY TOMSKANG | KMS04 \n COPYRIGHT TO TOMSKANG \n KMS04- SEARCHING PRIME V^";
    	char file_name[40];
    
    	system("cls");
    	textcolor(YELLOW, BLACK);
    
    	// ********** file open ********** //
    
    	fopen_s(&BIN, "pdata.bin", "rb");
    	sprintf_s(file_name, 40, "Decode 0-1%s.txt", FILE_N_READ);
    	fopen_s(&TXT, file_name, "wt");
    	if ((BIN == NULL) || (TXT == NULL)) {
    		cout << "file open failed ! " << endl << endl;
    	}
    
    	// ********** standard file output ********** //
    
    	while (TRUE) {
    		readCnt = fread((void*)arr, sizeof(pd), 5, BIN);
    
    		if (readCnt < 5) {
    			if (feof(BIN) != 0) {
    				for (int i = 0; i < readCnt; i++) {
    					if (arr[i] <= 1)
    						continue;
    
    					if (count == LINE_PER_PRIME) {
    						if (MODE == standard) { fprintf(TXT, "\n"); }
    						count = 0;
    					}
    
    					fprintf(TXT, "%.0lf %c", (long double)arr[i], (MODE == standard) ? '\t' : ' ');
    					count++;
    				}
    			}
    			else
    				cout << "decode fail!" << endl;
    			fprintf(TXT, "%s", ending);
    			cout << "fin" << endl;
    			break;
    		}
    		else {
    			for (int i = 0; i < 5; i++) {
    
    				if ((long double)arr[i] > (long double)FILE_NUM* (fnameCnt + 1)) {
    					cout << fnameCnt + 1 << "th file fin" << endl;
    					fprintf(TXT, "%s", ending);
    					fclose(TXT);
    					++fnameCnt;
    					sprintf_s(file_name, 40, "Decode %d%s-%d%s.txt", fnameCnt, FILE_N_READ, fnameCnt + 1, FILE_N_READ);
    					fopen_s(&TXT, file_name, "wt");
    					count = 0;
    				}
    
    				if (arr[i] <= 1)
    					continue;
    
    				if (count == LINE_PER_PRIME) {
    					if (MODE == standard) { fprintf(TXT, "\n"); }
    					count = 0;
    				} //*/
    				fprintf(TXT, "%.0lf %c", (long double)arr[i], (MODE == standard) ? '\t' : ' ');
    				count++;
    
    			}
    		}
    	}
    
    	fclose(BIN);
    	fclose(TXT);
    
    	cout << "decode success" << endl;
    	cout << "MADE BY TOMSKANG" << endl;
    	return 0;
    }

    [함수설명]

    int SETUP(void);

    말그대로 SETUP를 하는 함수입니다. 이미 파일에 데이터가 있을때, 'N'을 입력하면 SETUP을 하지 않습니다.

    int KMS04main(void);

    소수탐색을 하는 함수입니다. 이 함수의 시간복잡도를 이 프로그램의 시간복잡도로 적었습니다.

    int FtoT(void); // F(.bin) to Text

    디코딩을 하는 함수입니다. 프로그램을 런 하기 전 #define을 이용해 standard모드로 출력할지 list모드로 출력할지 정할 수 있습니다.


    ​[실행]

    KMS04.exe
    Decode.txt

    이상으로 KMS04(소수탐색 프로그램2.5)를 마칩니다.


    relation content

    C언어 소수탐색 프로그램 Ver2

     

    C언어 소수탐색 프로그램 Ver1

     

    KMS04 : C언어 소수탐색 프로그램 Ver1 (source)

    이 프로그램은 2019. 4. 28. 16:29에 네이버 블로그에서 작성되었습니다. 안녕하세요 tomskang입니다. 오늘은 간단하게 소수탐색 프로그램을 한번 만들습니다. 시간 복잡도는 O(Nsqrt(N))입니다. 소스코드

    kms-program.tistory.com

     

하면된다 學業報國