C1 조




Project #1
파스칼의 삼각형




C1
2012-03-17
목차
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
1. 프로젝트 수행 결과 보고서


프로젝트의 목적


    -    배열의 사용법을 안다.
    -    프로그램의 시간,공간 복잡도를 계산할 수 있다.




프로젝트의 내용


    -    배열을 이용하여 파스칼의 삼각형을 출력하는 프로그램을 작성하고, 시간 복잡도와 공간
         복잡도를 이용하여 보다 빠르고 메모리 손실이 작은 프로그램을 만들자.




프로젝트의 진행 방법


    -    전체적인 프로젝트 진행은 팀원들과의 협동을 통해 진행되며 각자의 역할을 분담하여 프
         로젝트 진행 속도와 완성도를 높이는 방향으로 진행된다.




프로젝트 결과


    -    50행 이하의 파스칼의 삼각형 출력에는 문제가 없으나 그 이상의 행에서는 소수점 이하
         의 오차가 발생하는 프로그램이 완성되었다.
    -    최종 검토 과정에서 생각지 못한 오류와 불필요한 메모리 손실이 발견되어 재 수정을 거
         쳤고 오차와 메모리손실을 줄였다.




참고문헌 및 웹
http://10albatross.tistory.com/27
http://carstart.tistory.com/122
http://skmagic.tistory.com/164
http://qwe1qwe.tistory.com/880
C로 쓴 자료구조론_HOROWITZ,Sahni,Anderson-Freed저 , wikepedia.org , httpispkorea.com ,




                                 2. 프로젝트 수행 일지




3월 6일 프로젝트 착수

    -   조 편성 및 프로젝트 문제 인식


    -   문제 인식 :배열을 이용하여 파스칼의 삼각형을 문제에서 요구하는 대로 출력 해야한다.
        사실상 파스칼의 삼각형 출력은 어려운 것이 아니다.
        하지만, 자료형 제한과 메모리와 시간의 균형을 맞추는 것이 매우 어려울 것이다.
    -   파스칼의                                                             삼각형이란?
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이기 때문에 , 걸러준다.
{ 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 을 대입받는다.
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;                 //입력받을 값의 변수
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;             //나눈값은 소수점이 있을 수 있으므로 소수점이하는 버리고
                                                            정수부분만 저장시킨다.
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;
}
            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();
void main(){
int x;
int y=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! 이다
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에 저
장한다.
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--;
        }
    }
}

자료구조 Project1

  • 1.
    C1 조 Project #1 파스칼의삼각형 C1 2012-03-17
  • 2.
    목차 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--; } } }