/*
 * -------------------------------------
 *     몬테카를로법에 의한 π 계산    *
 * -------------------------------------
 */

 

#include <stdio.h>
#include <stdlib.h>

#define NUM 1000

 

double rnd(void);

int main(void)
{
    double x, y, pai;
    int i,in=0;

    for (i=1; i<=NUM; i++){
        x=rnd();
        y=rnd();
        if (x*x+y*y<=1)
            in++;
    }
    pai=(double)4*in/NUM;
    printf("π값 = %f\n", pai);

    return 0;
}

double rnd(void)        /* 0 ~ 1 사이의 난수 */
{
    return (double)rand()/RAND_MAX;     // 0 ~ 1사이의 난수를 발생 시킨다.
}

 

//  몬테카를로법을 이용해서 PI값을 구한다. 0~1사이의 실수형 난수를 두 개 발생시킨후

이를 x, y라고 하자. 이러한 난수쌍을 어는 정도 발생시키면 1*1크기의 정사각형에 (x, y)로 표시

되는 점이 균일하게 흩뿌려진다. 따라서 정사각형의 면적과 1/4원 면적비는 흩뿌려진 난수의 개수

에 비례한다고 할 수 있다.

 

//  num을 1000으로 설정 해주었기 때문에 그다지 정확하지 않다. 값의 정확도는 난수 발생 횟수의

증가와  rnd()에 의해 발생하는 난수가 얼마나 균일하게 퍼지는지에 따라 크게 달라진다.

 

//*  몬테카를로법에 의한 면적 계산  *//

 

#include <stdio.h>
#include <stdlib.h>

#define NUM 1000

 

double rnd(void);

int main(void)
{
    double x, y, s;
   

    int i, in = 0;

   

   for (i=0; i<=NUM; i++){
        x = 2*rnd();
        y = rnd();
        if (x*x/4+y*y<=1)
            in++;
    }
    s = 4.0*(2.0*in/NUM);

    printf("타원의 면적 = %f\n", s);

   

    return 0;
}

 

double rnd(void)       /* 0 ~ 1 사이의 난수 발생 */
{
    return (double)rand()/RAND_MAX;
}

 

// x에 0~2사이의 난수, y에 0~1사이의 난수를 대입해서 2*1의 직사각형 내부에 균일하게

퍼뜨린다. PI값 계산 알고리즘을 정확하게 이해한다면, 면적 계산은 쉽게 해결 된다.

 

// 1번 예제

#include <stdio.h>
#include <math.h>             // sin, cos 함수를 사용하기 위해서...

 

void main()
{
  int degree = 0;
  double radian = 0.0;

  printf("원하시는 각(degree)을 입력하세요 :  ");
  scanf("%d", degree);

    // sin, cos 함수들은 일반각을 이용하지 않고 라디안형식의 각을 S
    // 사용하기 때문에 라디안 값으로 변환해야 한다
.
  radian = degree*3.141592/180;

  printf("n");
  printf("cos %d = %fn", degree, cos(radian));
  printf("sin %d = %fn", degree, sin(radian));
}


 

// 2번 예제

#include  <stdio.h>                  
#include  <math.h>                  
#define PI 3.141592654       // <-- 파이값을 정의 합니다

 

void main()
{
     double vSin , vCos , vTan;             // <-- sin , cos , tan 저장할 변수입니다
                                                       // 각 함수들 반환값이 double형이라
                                                      // double형으로 선언합니다
     int Degree;                                 // <-- 각도를 저장할 변수입니다

     printf("각도를 입력하세요 : ");
     scanf("%d" , &Degree);                  // 각도를 입력받습니다

     vSin = sin(Degree * (PI / 180));     // 각도를 라디언으로 바꿔서 sin 함수안에 넣습니다
     vCos = cos(Degree * (PI / 180));
     vTan = tan(Degree * (PI / 180));

     printf("sin = %f \ncos = %f \ntan = %f\n" , vSin , vCos , vTan);
}

 

/*
 * -------------------------
 *     유클리드 호제법     *
 * -------------------------
 */

 

#include <stdio.h>

int main(void)
{
    int a,b,m,n;

    printf("두 정수를 입력하세요. : ");
    scanf("%d %d", &a, &b);

    m=a; n=b;
   

    while (m!=n){
        if (m>n)
            m=m-n;
        else
            n=n-m;
    }
    printf("최대공약수 = %d\n", m);

    return 0;
}

 

 

// 실행결과

    두 정수를 입력하시오 : 128 72

    최대공약수 = 8

 

// 기계적인  반복으로 최대공약수를 구하는 방법인 컴퓨터 지향 알고리즘으로는

유클리드(Euclid)호제법이 있다. 알고리즘을 간단히 정리하면 다음과 같다.

    

     1. m과 n이 같지 않으면 다음을 반복한다.

    2. m>n이면 m-n, 그렇지 않으면 n=n-m이다.

    3. m(또는 n)이 구하고자 하는 최대공약수 다.

 

/*
 * ---------------------------
 *      파스칼의 삼각형      *
 * ---------------------------
 */

 

#include <stdio.h>
#define N 12

long combi(int,int);

int main(void)
{
    int n,r,t;

    for (n=0;n<=N;n++){
        for (t=0;t<(N-n)*3;t++)        /* 공백 */
            printf(" ");
        for (r=0;r<=n;r++)
            printf("%3ld   ",combi(n,r));
        printf("\n");
    }

 return 0;
}

long combi(int n,int r)
{
    int i;
    long p=1;

    for (i=1;i<=r;i++)
        p=p*(n-i+1)/i;
    return p;
}

 

// nCr을 구하는 프로그램을 이용해서 파스칼의 삼각형을 위와 같이 나타낼 수 있다.

 

/*
 * --------------------
 *     순위 매김     *
 * --------------------
 * 시험점수의 점수별 순위를 구한다.

 */

 

#include <stdio.h>

#define Num 10

int main(void)     /* 순위 매김 */
{
    static int a[]={56,25,67,88,100,61,55,67,76,56};
    int rank[Num];
    int i,j;

    for (i=0;i<Num;i++) {
        rank[i]=1;
        for (j=0;j<Num;j++) {
            if (a[j]>a[i])
                rank[i]++;
        }
    }

    printf("   점수  순위\n");
    for (i=0;i<Num;i++){
        printf("%6d%6d\n",a[i],rank[i]);
    }

    return 0;
}

 

// 위의 순위를 구하는 알고리즘에서는 데이터가 n개인 경우, 반복 횟수가 n2이 된다. 따라서

데이터 수가 증가하면 처리하는 데 시간이 많이 걸린다. 따라서 반복 횟수를 줄이기 위한

순위 매김 알고리즘을 생각해본다. 다음 알고리즘이 그 예제이다.

 

// 개선된 순위 매김

 

#include <stdio.h>

#define Num 10

#define Max 100

#define Min 0

 

int main(void)    

{
    static int a[] = {56,25,67,88,100,61,55,67,76,56};
    int i, rank[Max+2];
   

    for (i=Min; i<Max; i++)
         rank[i]=0;                        //  0으로 초기화
        for (i=0; i<Num; i++)         //  각 점수를 첨자로 하는 배열요소에 +1
           rank[a[i]]++;                          
   

    rank[Max+1] = 1;                 //  바로 오른쪽 요소의 값을 더함

    for(i=Max; i>=Min; i--)

       rank[i] = rank[i]+rank[i+1];


    printf("   점수  순위\n");
    for (i=0; i<Num; i++){
        printf("%6d%6d\n", a[i], rank[a[i]+1]);    // 점수 +1의 위치에 순위가 저장됨
    }

    return 0;
}

 

/*
 * ------------------------------------
 *     랜덤한 순열

 * ------------------------------------
 */

 

#include <stdio.h>
#include <stdlib.h>

#define N 20

int irnd(int);

int main(void)
{
    int i,j,d,a[N+1];

    for (i=1;i<=N;i++)
        a[i]=i;

    for (i=N;i>1;i--){
        j=irnd(i-1);
        d=a[i];a[i]=a[j];a[j]=d;
    }

    for (i=1;i<=N;i++)
        printf("%d ",a[i]);

    printf("\n");

    return 0;
}

 

int irnd(int n)        /* 1 ~ N 의 난수 */
{
    return (int)(rand()%n + 1);
}

 

// a[1]~a[N]에 1~N의 수를 순서대로 저장한다.

1~N-1중에서 난수 j를 얻는다. 이것을 첨자로 하는 배열 a[j]와 a[N]을 교환한다. 이렇게 해서

a[N]항의 순열은 확정된다.

/*
 * ---------------------------------------
 *     2 ~ N 사이의 모든 소수를 추출     *
 * ---------------------------------------
 */


#include <stdio.h>
#include <math.h>

#define NUM 1000

int main(void)
{
    static int prime[NUM/2+1];
    int i,n,m=0,Limit;

    for (n=2;n<=NUM;n++){
        Limit=(int)sqrt(n);
        for (i=Limit;i>1;i--){
            if (n%i == 0)
                break;
        }
        if (i==1)
            prime[m++]=n;
    }

    printf("2 ~ %d 사이의 소수\n", NUM);
    for (i=0;i<m;i++)
        printf("%5d",prime[i]);

    printf("\n");
   
    return 0;
}


// 2~N 까지의 모든 정수 중에서 소수를 모두 구한다.

/*
 * --------------------
 *      소인수분해    *
 * --------------------
 */


#include <stdio.h>

int main(void)
{
    int a,n;

    while (printf("Number ? "),scanf("%d",&n)!=EOF) {
        a=2;
        while (n>=a*a){
            if (n % a ==0){
                printf("%d*",a);n=n/a;
            }
            else
                a++;
        }
        printf("%d\n",n);
    }
   
    return 0;
}


// 양의 정수를 소수의 곱으로 분해하는 것을 소인수 분해라고 한다.

/*
 * ----------------------
 *      소수의 판정     *
 * ----------------------
 */


#include <stdio.h>
#include <math.h>

int main(void)
{
    int i,n,Limit;

    while (printf("data? "),scanf("%d",&n)!=EOF) {
        if (n>=2){
            Limit=(int)sqrt(n);
            for (i=Limit;i>1;i--) {
                if (n%i == 0)
                    break;
            }
            if (i==1)
                printf("소수\n");
            else
                printf("소수가 아님\n");
        }
    }
   
    return 0;
}

 

// 소수란 다음과 같이 1과 자기 자신외에는 약수를 갖지 않는 수를 말한다.

    2, 3, 5, 7 , 11 (단, 1은 소수가 아니다.)

// n이 소수인지 아닌지는 n이 n외의 정수로 나누어 떨어지는지 아닌지를 통해서 알 수 있다.

n이하의 정수에서 2까지의 수로 나누어서 떨어지는 수가 있으면 소수가 아니므로 루프를

빠져나오면 된다.

+ Recent posts