프로그래밍 기법 최적화 프로그래밍
좋은 프로그램이란? 생산성(Productivity) 효율성(Efficiency) 빠른 시간 안에 프로그램을 완성, 생산 편리한 유지보수 효율성(Efficiency) 빠른 시간 안에 주어진 task를 완료
소프트웨어 개발 비용분석
1. 생산성 Readiblity(가독성; 可讀性) 해결방안 프로그램의 수행 흐름을 쉽게 파악할 수 있어야 함 유지보수를 위한 비용을 절약 해결방안 외형적인 측면 프로그래밍 작성지침 구조적 측면 Structured Programming, Object-Oriented Programming
가독성을 위한 코딩 Rule 올바르고 명확한 변수명칭을 사용 설명문(comment)를 충분히 사용 a, b, x, y, … 등과 같은 막연한 변수이름 지양 Sum, divider, count, … Text1, Combo1, Button1, … txtInput, txtResult, cmbDept, btnExecute 설명문(comment)를 충분히 사용 간단 명료하며 기능을 충분히 설명 특정 함수 혹은 명령문 앞에 위치시킴
프로그래밍 코딩 Rule(계속) 들여쓰기(Indentation) { }의 위치 적절한 빈 줄의 삽입 특히 제어구조(반복, 조건 등)에 유의 { }의 위치 { : if, else, do, while, struct, class, 함수이름과 같은 줄에 위치 혹은 바로 아래 줄 } : 해당 명령문에 열을 맞춤 적절한 빈 줄의 삽입
프로그램 예제 class CMath { // 팩토리알 값을 배열에 저장하고 출력하기. // 다음 두 줄은 정적변수에 관한 정의 이다.. static const maxFactorial : int = 5; static const factorialArray : int[] = new int[maxFactorial]; static CMath { // 패토리알 값의 배열을 초기화하고. // factorialArray[x] = (x+1)! 의 관계를 이용한다 factorialArray[0] = 1; for(var i : int = 1; i< maxFactorial; i++) { factorialArray[i] = factorialArray[i-1] * (i+1); } // 초기화가 수행되었을을 알림. print(“초기화 완료."); static function factorial(x : int) : int { return x * factorialArray[x-1]; }; print(“팩토리알 테이블 인쇄:"); for(var x : int = 1; x <= CMath.maxFactorial; x++) { print( x + "! = " + CMath.factorial(x) );
2. 효율성(Efficiency) 가급적 빠른 연산연산자를 이용한다. 연산자의 수행속도 예 +, -, <<, >> * /, % 예 3*i a/b/c a/2 3*i → i+i+I a/b/c → a/(b*c) a*0.5
이진수로 바꾸기의 예제 #include <stdio.h> void main() { int number, i; int bit = 0x8000; //만약4자리 발생하려면 0x8, 8자리는 0x80으로, // 24자리는 0x800000 while(1) { printf("숫자를 입력하시오 : "); scanf("%d", &number); if(number<0) break; for(i = 0; i < 16; i++) if((number & bit)) printf("1"); else printf("0"); number = number << 1; //1비트 왼쪽 시프트 } printf("\n"); #include <stdio.h> void main() { int number, i; int temp; while(1) { printf("숫자를 입력하시오 : "); scanf("%d", &number); if(number<0) break; temp=number; for(i = 0; i < 16; i++) { printf("%d", temp%2); temp=temp/2; } printf("\n");
비교해보자 #include <stdio.h> int getAvg(int begin, int end, int count) { int i = 0, avg = 0; for(i = begin; i <= end; i++) { avg += i / count; } return avg; #include <stdio.h> int getAvg(int begin, int end, int count) { int i = 0, sum = 0; for(i = begin; i <= end; i++) sum += i; } return sum/count;
비교해보자 이것을 매크로로 바꿔보자. #define SWAP(a, b) temp = a; a = b; b = temp; … void swap(int &a, int &b) { int temp = a; a = b; b = temp; } 여기서 int temp 와 같은 로컬 변수를 사용하게 되므로 만일 루프 내에서 while(조건) .... swap(a, b); 와 같이 사용할 경우 이 함수는 ... 와 같이 바뀌는데 매번 temp변수의 선언이 필요하고 저장 위치가 명시적이지 못함. 이것을 매크로로 바꿔보자. #define SWAP(a, b) temp = a; a = b; b = temp; … int temp; while( 조건) { .... SWAP(a, b) } int temp 가 루프 바깥에 위치하게 된다. 변수의 위치를 명시적으로 지정하여 속도를 향상시킬 수 있다.
기타사항 인수분해 활용 함수호출은 가급적 피하자 임시변수는 가급적 피하자 a = b*(e+f) – c*(e+f) +d*(e+f) → a = (b-c+d)*(e+f) 함수호출은 가급적 피하자 log(a) + log(b) → log(a*b) 임시변수는 가급적 피하자 t1 = a+b; t2 = c*d; x = t1+t2 x = a+b+c*d;
비교해보자 #include <stdio.h> int getSum(int begin, int end) { int i = 0, sum = 0; for(i = begin; i <= end; i++) sum += i; } return sum; int main(void) if(getSum(1, 100) >= 5000) printf("sum : %d\n“,getSum(1, 100)); return 0; #include <stdio.h> int getSum(int begin, int end) { int i = 0, sum = 0; for(i = begin; i <= end; i++) sum += i; } return sum; int main(void) int sum = getSum(1, 100); if(sum >= 5000) printf("sum : %d\n", sum); return 0;
if문의 관리 가능성이 큰 조건을 앞에 사용함 P(x=3) > P(x=2) >P(x=1)라고 하면 if (x=1) … else if (x=2) … else (x=3) if (x=3) … else if (x=2) … else (x=1) 예를 들어 상금 결정문제 1~100숫자 사이에 20의 배수이면 상금이 100원, 7의 배수이면 50원, 짝수이면 20원이라고 할 때 각자의 상금을 결정해보자
조건식의 순서 P(a=x) > P(b=x)이면 if(a==x || b==x) if(b==x && a==x)
Structured Programming Object-Oriented Programming 프로그램의 외형적 측면 Structured Programming Object-Oriented Programming
구조적 프로그래밍 (Structured Programming) GOTO-less 프로그래밍 1960년대 말 Software Crisis( by Dijkstra) 기본구조 Sequence Structure Selection Structure Repetition Structure Top-Down Programming 문제를 큰 단위부터 구성하고 작은 단위로 세분화 Modular Programming 전제 프로그램을 독립된 작은 모듈(module)로 구성
간단한 예 조합 구하기 Top-Down 두수를 입력 받음 팩토리알 구함 조합 계산
프로그램 구조화 예제 반복 반복 #include <stdio.h> int main(void) { int a, b; a = get_integer(); b = get_integer(); printf("C(%d, %d) = %d \n", a, b, combination(a, b)); return 0; } int combination(int n, int r) return (factorial(n)/(factorial(r) * factorial(n-r))); int get_integer(void) int n; printf("정수를 입력하시오: "); scanf("%d", &n); return n; int factorial(int n) int i; long result = 1; for(i = 1; i <= n; i++) result *= i; return result; #include <stdio.h> int main(void) { int a, b, c, d, e, i; printf("정수를 입력하시오: "); scanf("%d", &a); scanf("%d", &b); for(i = 1; i <= a; i++) c *= i; for(i = 1; i <= b; i++) d *= i; for(i = 1; i <= a-b; i++) e *= i; printf("C(%d, %d) = %d \n", a, b, c/(d*e); } 반복 반복
객체지향 프로그래밍 (Object-Oriented Programming; OOP Structured Programming vs. OOP 공통점 GOTO-less Programming 모듈화 프로그래밍 차이점 Structured Programming Function : 중심 역할 Data : 부수적인 역할 OOP Data : 중심 역할 Function : 부수적인 역할
간단한 예 Data : 자동차, 책, 사과, 물건, 배 Function : 소유하다, 타다, 먹다, 읽다, 맛있다 Structured Programming 자료가 function에 노출되어 있음 자동차 : 먹다 사과 : 타다 OOP 자료가 중심이 되어 function과 하나로 묶음(캡슐화, 자료 은닉) 물건 소유하다 상속 사과 먹다, 맛있다 배 먹다 자동차 타다 책 읽다
프로그램 구조 비교 struct employee class employee (자료구조) {private :자료구조 initialize(employee); … show_data(employee); main() {함수호출} class employee {private :자료구조 public :initialize show_data … main() {객체에 대한 메세지전달) 자료노출 자료은닉 자료은닉 : 외부에서는 자료구조를 알 필요가 없다
OOP의 특징 프로그래밍 방식 장점 객체를 구성 구성된 객체를 조립 Bottom-Up 프로그래밍 재사용이 매우 용이 차를 타고 가며 책을 읽었다 차를 타고 가며 사과를 먹었다 확장성(extensibility) 수정이 용이 : 객체 내에서만 수정 작업이 이루어짐
C++ 프로그래밍 예제 실행결과 Result : 11 Result : -1 #include <iostream.h> class Counter { private: int value; public: void set(int n) {value = n;} void inc() {++value;} void dec() {--value;} int val() {return value;} }; main() { Counter cnt; cnt.set(10); cnt.inc(); cout << "Result : " << cnt.val() << '\n'; cnt.set(0); cnt.dec(); } 실행결과 Result : 11 Result : -1