목차
1. 프로젝트 수행 결과 보고서 ............................................................................................................ 3
프로젝트의 목적 ..................................................................................................................................... 3
프로젝트의 내용 ..................................................................................................................................... 3
프로젝트의 진행 방법 ............................................................................................................................ 3
프로젝트 결과 ......................................................................................................................................... 3
참고문헌 및 웹 ....................................................................................................................................... 3
2. 프로젝트 수행 일지 ........................................................................................................................... 4
3월 6일 프로젝트 착수 .......................................................................................................................... 4
3월 10일 일정계획 및 진행방법 토의 .................................................................................................. 5
3월 13일 업무 분담 및 1차 소스 작성 ................................................................................................ 5
3월 15일 2차 소스 작성 ........................................................................................................................ 6
3월 18일 소스 완료 및 최종보고서 작성 ............................................................................................. 7
3월 20일 최종 소스 작성 및 최종보고서 검토 .................................................................................. 10
3.
1. 프로젝트 수행결과 보고서
프로젝트의 목적
- 배열의 사용법을 안다.
- 프로그램의 시간,공간 복잡도를 계산할 수 있다.
프로젝트의 내용
- 배열을 이용하여 파스칼의 삼각형을 출력하는 프로그램을 작성하고, 시간 복잡도와 공간
복잡도를 이용하여 보다 빠르고 메모리 손실이 작은 프로그램을 만들자.
프로젝트의 진행 방법
- 전체적인 프로젝트 진행은 팀원들과의 협동을 통해 진행되며 각자의 역할을 분담하여 프
로젝트 진행 속도와 완성도를 높이는 방향으로 진행된다.
프로젝트 결과
- 50행 이하의 파스칼의 삼각형 출력에는 문제가 없으나 그 이상의 행에서는 소수점 이하
의 오차가 발생하는 프로그램이 완성되었다.
- 최종 검토 과정에서 생각지 못한 오류와 불필요한 메모리 손실이 발견되어 재 수정을 거
쳤고 오차와 메모리손실을 줄였다.
참고문헌 및 웹
http://10albatross.tistory.com/27
http://carstart.tistory.com/122
http://skmagic.tistory.com/164
4.
http://qwe1qwe.tistory.com/880
C로 쓴 자료구조론_HOROWITZ,Sahni,Anderson-Freed저, wikepedia.org , httpispkorea.com ,
2. 프로젝트 수행 일지
3월 6일 프로젝트 착수
- 조 편성 및 프로젝트 문제 인식
- 문제 인식 :배열을 이용하여 파스칼의 삼각형을 문제에서 요구하는 대로 출력 해야한다.
사실상 파스칼의 삼각형 출력은 어려운 것이 아니다.
하지만, 자료형 제한과 메모리와 시간의 균형을 맞추는 것이 매우 어려울 것이다.
- 파스칼의 삼각형이란?
5.
3월 10일 일정계획및 진행방법 토의
- 일정계획 및 진행방법 토의
- 일정계획: 3월 13일 2차 미팅 – 업무 분담 및 1차 소스 작성
3월 15일 3차 미팅 – 2차 소스 작성 및 오차 수정
3월 18일 4차 미팅 – 소스 완료 및 최종 보고서 작성
3월 19일 5차 미팅 – 최종보고서 검토 및 프로젝트 완료
3월 20일 6차 미팅 – 최종보고서 검토내용 적용 및 소스 수정
3월 22일 프로젝트 마감 제출 발표
- 진행방법:토론과 토의를 바탕으로 프로젝트를 수행하며, 팀 내에서 업무분담을 통해 작업
의 효용성을 높이며 토의와 수정을 거쳐 완성도 높은 프로젝트 결과물을 도출한다.
소스 작성에 있어서는 배열을 먼저 선언하고 출력 하는 방법을 고려한다.
3월 13일 업무 분담 및 1차 소스 작성
- 업무분담 : 조장 : 09학번 최고봉 – 최종보고서작성, 발표
팀원 : 08학번 고충욱– 자료조사, 보고서작성
11학번 서상현 – 보고서작성, 스케쥴링
11학번 김성진 – 소스작성, 자료조사
11학번 김지환 – 자료조사, 스케쥴링
- 1차 소스 작성
당초 생각했던 배열을 먼저 선언하고 출력하는 방식은 메모리손실이 크고 시간이 오래
걸릴것으로 예상되므로 재귀함수를 이용하는 방법을 이용하기로 했다.
#include <stdio.h>
int Sum (int n, int m, int *sum); // Sum 함수선언
int Sum (int n, int m, int *sum) // Sum 함수정의 (n-1)(m-1)+(n-1)(m)을 이용한다.
{
If (m < = 1 ) // m이 1이되면 값은 무조건 1이기 때문에 , 걸러준다.
6.
{ sum +=1; // 조건에 걸릴경우 sum 에 1을 더해주어 값을 더한다.
Break ; }
If(n<m)
Break; // m이 n보다 커지는경우가 발생하면 바로 종료시켜준다.
Sum(n-1,m-1,sum); // (n-1)(m-1)에 해당하는 부분이다.
Sum(n-1,m,sum); // (n-1)(m)에 해당하는 부분이다.
}
Int main (void)
{
Intn,m,sum;
+
Sum = 0;
Scanf(“%d %d”, &n , &m);
Sum(n,m,sum); //(n,m)을 함수에 대입시킨다.
Printf(“%d”, sum);
Return 0;
}
이 방법은 자료형 제한과 시간적인 결함으로 인해 보완할 점이 많다. 라는 결론을 내렸
다.
3월 15일 2차 소스 작성
- 3월 13일 작성한 소스가 자료형의 제한에 걸리는 동시에 시간이 오래 걸린다는 오점이
있었고, 그래서 우리는 공식을 저장하고 그 공식에 입력 받은 값을 대입하여 값을 얻어내
는 방법을 이용한 소스를 작성하기로 하였다. 하지만 새로운 소스는 메모리 손실이 크다
는 오점이 있다.
#include <stdio.h>
Intmain(void)
{
Intn,m,sum,p,r,I,k; //연산을 위한 변수와 숫자를 대입받을 변수선언
Scnaf(“%d %d”, &n,&m); // n 과 m 을 대입받는다.
7.
P = r= 1; //곱셈연산을 하기위해 초기값을 1 로 설정
For(i=1;i<m;i++) // r! 을 구한다.
r *= i;
k = m-1;
for(i=n-1;;i--) // nPr을 구한다.
{
If(k==0)
Break;
k--;
p *= i;
}
sum = p/r; // nPr / r! 을 연산한다.
Printf(“%d”, sum); // 출력.
Return 0;
}
3월 18일 소스 완료 및 최종보고서 작성
- 우리는 메모리보다는 실행시간에 중점을 두고 프로젝트를 진행 해왔고, 앞서 작성한 두
소스 (재귀함수이용,공식대입)중에 공식대입소스를 이용하기로 하였다. 소스 검토 과정중
에 마주한 어려움으로는 자료형의크기제한으로 인한 오류와 연산의 어려움 이였다. 이를
해결하기 위하여 배열을 크게 선언하여 공간을 확보하여 배열에 결과값을 저장하는 방식
을 통해 결과값을 출력하기로 하였고 연산의 어려움을 해결하기 위해 곱과 분을 따로 하
기로 하였다 아래와 같은 소스를 완성하였다.( 추가 설명은 각주에서).
#include <stdio.h>
#include <stdlib.h>
double sum[400]; //계산한값을 받을 더블형 배열
int size; //반복문에서 사용될 배열의 크기, 배열은 위의 크기로 선언되나 반복문에서는
필요한부분만 사용하여 연산
intm,n; //입력받을 값의 변수
8.
void Calculation(){ //답을 구하는 방법은 공식을 사용. 공식은 nCm = n!/m!/(n-m)!
= (n*(n-1)*(n-2)*...*(n-m+1)/m! 이며 오른쪽 식을 사용하여 답을 구하도록했다.
double a,b; //계산에필요한 변수
int c; //배열번호를 담당하는 변수
double buffer,temp; //연산에서 임시로 저장할 변수
int s=0;
buffer=0;
for(a=n-1,b=m-1;a>=(n-m+1)||b>0; ){
c=size-1;
if(a>=(n-m+1)){ //공식의 분자부분. n*(n-1)*(n-2)*...*(n-m+1)를 수행한다
while(c>=0){ //sum[c]에 값을 곱했을때 값이 일정값을 넘으면 sum[c+1]에 넘치는 값을 넘기
도록 했다.
sum[c]=sum[c]*a;//sum[0]은 기본적으로 1이다. 다른 값은 0이다.
if(sum[size-1]!=0) //반복문을 돌리는 배열중 최상위 배열이 0이 아닐때 사용하는 배열을 늘린다.
기본적으로 sum[0]과 sum[1] 두개를 사용한다
size++;
if(sum[c]>=1e+9){ //값이 9자리를 넘을때 넘치는 값을 나누어 다음 배열에 넘기는 부분이다.
temp=(unsigned)(sum[c]/(1e+9));
sum[c+1]=sum[c+1]+temp;
sum[c]=sum[c]-(temp*(1e+9));
}
c--;
}
a--;
}
else if(b>0&&a==(n-m)){ //위의 분자부분 연산이 끝나면 분모부분의 연산을 수행한다. 여기서
는 매숫자마다값을 나누어주어 저장하는 식으로 진행한다.
while(c>=0){
if(sum[c]!=0&&s==0) //값이 존재하는 배열이 나올때까지 연산을 하지않기위해
이 구문을 넣었다.
s=1;
if(s==1){ //연산은 최상위 배열값부터 나누어 내려가며
나눈값소수점이하 부분에 1e+9(1000000000)를 곱하여
if(sum[c]/b>=1){ //buffer변수에 저장한다.
temp=(sum[c]/b)+buffer; //배열에 buffer를 더하고(첫 buffer는 0이다.) 연산할 값을
나눈후임시값에 저장한다.
sum[c]=(unsigned)temp; //나눈값은 소수점이 있을 수 있으므로 소수점이하는 버리고
정수부분만 저장시킨다.
9.
buffer=(temp-sum[c])*(1e+9); //버퍼에 배열을 나누값의 정수부분을 뺀 나머지 소수부분에
1e+9를 곱해준다.
if(c==0){ //최하위 배열의 경우 연산후 다음 연산을 위해
버퍼에 0을 저장한다.
buffer=0;
s=0;
}
}
else{ //배열값을나눴을때 1미만일 경우 배열에 0을 저장하고
나머지값은 buffer에 저장한다.
buffer=sum[c]/b*(1e+9);
sum[c]=0;
}
}
if(sum[c]>=1e+9){ //만약 배열에 저장된값이 1e+9보다 클때 넘치는 값을 윗 배열로 넘
긴다.
temp=(unsigned)(sum[c]/(1e+9));
sum[c+1]=sum[c+1]+temp;
sum[c]=sum[c]-(temp*(1e+9));
}
c--;
}
b--;
}
}
}
void main(){
int x;
int y=0;
printf("열을 입력해주세요 : ");
scanf("%d",&n);
printf("행을 입력해주세요 : ");
scanf("%d",&m);
size=2;
for( x=0 ; x<400 ; x++ ){ //값을 계산할 배열 값을 초기화.
첫번째 배열만 1로 선언하고 나머지는 모두 0으로 선언
if( x==0 ){
sum[x]=1;
continue;
10.
}
sum[x]=0;
}
Calculation(); //값을 구하기위한 계산함수
printf("%d번째 행의 %d번째 열의 숫자는 ",n,m);
for( x=size-1 ; x>=0 ; x-- ){ //답을 출력하는 반복문. 계산과정에서 값을 저장하는
자료형의 크기의 한계를 극복하기위해
if(sum[x]!=0||y==1){ //일정 값을 넘어가면 넘치는 부분을 다음 배열에
저장하도록 하였기 때문에 결과값이 나누어져있어
if(y==0){ //한번에 출력할수없어 부득이 반복문을 사용하였다.
printf("%.f",sum[x]); //배열이 0일때는 출력하지 않도록 했고 결과값이 나오면
그 밑의 값은 모두 출력하도록했다.
y=1;
continue;
}
printf("%09.f",sum[x]);
}
}
printf("입니다.n");
_getch();
- 위 코드에는 치명적인 결함이 있다. 오차가 생기는 점이다. 그 이유는 값을 나누는 과정
에서 자료형의 소수점 정밀도 때문이다. 따라서 결과값의 정확한 자릿수 정도는 구할 수
있을지 모르나 정확한 결과 값을 기대하긴 어렵다. 단 50행 이하의 적은 숫자는 정확한
값을 구할 수 있다.
3월 20일 최종 소스 작성 및 최종보고서 검토
- 배열크기가 불필요하게 커서 400 - >160 으로 축소 하였고, 연산 과정에서 오류가 발생해
서 최종 수정을 했다. (sum[0]가ㅏ 0이됬을 때 나눗셈 과정에서 숫자를 들여오지 못하는
오류)
#include <stdio.h>
#include <stdlib.h>
double sum[160]; //계산한값을 받을 더블형 배열
int size; //반복문에서 사용될 배열의 크기,배열은 위의 크기로 선언되나
반복문에서는필요한부분만 사용하여 연산
intm,n; //입력받을 값의 변수
void Calculation();
11.
void main(){
int x;
inty=0;
printf("열을 입력해주세요 : ");
scanf("%d",&n);
printf("행을 입력해주세요 : ");
scanf("%d",&m);
size=2;
for( x=0 ; x<160 ; x++ ){ //값을 계산할 배열 값을 초기화. 첫번째 배열만
if( x==0 ){//로 선언하고 나머지는 모두 0으로 선언
sum[x]=1;
continue;
}
sum[x]=0;
}
Calculation(); //값을 구하기위한 계산함수
printf("%d번째 행의 %d번째 열의 숫자는 ",n,m);
for( x=size-1 ; x>=0 ; x-- ){ //답을 출력하는 반복문. 계산과정에서 값을
//저장하는 자료형의 크기의 한계를 극복하기위해
if(sum[x]!=0||y==1){ //일정 값을 넘어가면 넘치는 부분을 다음 배열에
//저장하도록 하였기 때문에 결과값이 나누어져있어
if(y==0){ //한번에 출력할수없어 부득이 반복문을 사용하였다.
printf("%.f",sum[x]); //배열이 0일때는 출력하지 않도록 했고 결과값이
//나오면 그 밑의 값은 모두 출력하도록했다.
y=1;
continue;
}
printf("%09.f",sum[x]);
}
}
printf("입니다.n");
getch();
//이 코드에는 치명적인 결함이 있는데 값을 나누는 과정에서 자료형의 소수점 정밀도에 의해 오차가 생긴다는 점이다.
//따라서 결과값의 정확한 자릿수 정도는 구할 수 있을지 모르나 정확한 결과값을 기대하긴 어렵다
//다만 50행 이하의 적은 숫자는 정확한 값을 구할 수 있다.
}
void Calculation(){ //답을 구할때에는 공식을 사용했다.
//공식은 aCb = a!/a!/(a-b)! = (a*(a-1)*(a-2)*...*(a-b+1)/b! 이다
12.
double a,b; //계산에필요한 변수
int c; //배열번호를 담당하는 변수
double buffer,temp; //연산에서 임시로 저장할 변수
int s=0;
buffer=0;
for(a=n-1,b=m-1;a>=(n-m+1)||b>0; ){
c=size-1;
if(a>=(n-m+1)){ //공식의 분자부분. n*(n-1)*(n-2)*...*(n-m+1)를 수행한다
for(;c>=0;c--){ //sum[c]에 값을 곱했을때 값이 일정값을 넘으면
//sum[c+1]에 넘치는 값을 넘기도록 했다.
sum[c]=sum[c]*a; //sum[0]은 기본적으로 1이다. 다른 값은 0이다.
if(sum[c]>=1e+9){ //값이 9자리를 넘을때 넘치는 값을 나누어 다음 배열에 넘기는 부분이다.
temp=(unsigned)(sum[c]/(1e+9));
sum[c+1]=sum[c+1]+temp;
sum[c]=sum[c]-(temp*(1e+9));
}
if(sum[size-1]!=0) //반복문을 돌리는 배열중 최상위 배열이 0이 아닐때 사용하는 배열을 늘린다.
size++;
}
a--;
}
else if(b>0&&a==(n-m)){ //위의 분자부분 연산이 끝나면 분모부분의 연산을 수행한다.
//여기서는 매숫자마다 값을 나누어주어 저장하는 식으로 진행한다.
for(;c>=0;c--){
if(sum[c]!=0&&s==0) //값이 존재하는 배열이 나올때까지 연산을 하지않기위해 이 구문을 넣었다.
s=1;
if(s==1){ //연산은 최상위 배열값부터 나누어 내려가며 나눈값의
//수점이하 부분에 1e+9(1000000000)를 곱하여
if(sum[c]/b>=1){ //buffer변수에 저장한다.
temp=(sum[c]/b)+buffer; //배열에 buffer를 더하고(첫 buffer는 0이다.) 연산할 값을 나눈후임시값에 저장
한다.
sum[c]=(unsigned)temp; //나눈값은 소수점이 있을 수 있으므로 소수점이하는 버리고 정수부분만 저장
시킨다.
buffer=(temp-sum[c])*(1e+9); //버퍼에 배열을 나누값의 정수부분을 뺀 나머지 소수부분에 1e+9를 곱해준다.
}
else if(sum[c]==0)
sum[c]=buffer;
else{ //배열값을나눴을때 1미만일 경우 배열에 0을 저장하고 나머지값은 buffer에 저
13.
장한다.
buffer=sum[c]/b*(1e+9);
sum[c]=0;
}
}
if(c==0){
buffer=0; //최하위 배열의 경우 연산후 다음 연산을 위해 버퍼에 0을 저장한
다.
s=0;
}
if(sum[c]>=1e+9){ //만약 배열에 저장된값이 1e+9보다 클때 넘치는 값을 윗 배열로 넘긴다.
temp=(unsigned)(sum[c]/(1e+9));
sum[c+1]=sum[c+1]+temp;
sum[c]=sum[c]-(temp*(1e+9));
}
}
b--;
}
}
}