본문 바로가기
[Public] 수학/수치해석

[Hermeneutics] 3. 변수의 범위를 초과하는 산술 연산(1) <덧셈, 뺄셈>

by 차출발 2009. 10. 16.
반응형

[수치해석]

3. 변수의 범위를 초과하는 산술 연산 (1) <덧셈, 뺄셈>

 

 

2009. 10. 15

 

이번에는 변수의 제한된 범위를 넘어서는 산술연산을 해보겠다.

 

먼저 예제 1을 보자

 

void Ex1()

{

       unsigned long num1 = 4294967296;

       printf("1....  %u\n", num1);

 

       unsigned long num2 = 4294967295;

       printf("2....  %u\n", num2);

 

 

       unsigned long num3 = 4294967295;

       printf("3....  %d\n", num3);

 

       printf("4....  unsigned long : %dByte\n", sizeof(unsigned long));

       printf("5....  signed long : %dByte", sizeof(signed long));

 

}

 

실행 결과는 다음 같다.

 

 

먼저 1번 예제는 unsigned long의 범위가 0 ~ 4294967295 이기 때문에 4294967296의 출력은 0이 나타 나는 것을 알 수 있다. 한마디로 범위를 넘어서고 다시 첨부터 시작이라 할 수 있다. 쉽게 말하면 4294967297 1로 출력되고 4294967298 2로 …. 이런식다.

2번 예제와 3번 예제는 셋트이다.

이것은 printf 함수에서 %u 의 데이터를 %d로 표현 할 경우를 나타낸다.

 

4번과 5번도 셋트다.

Sizeof 는 어떤 자료형의 메모리에서 차지하는 Byte단위로 크기를 알려준다.

여기서 사이즈는 unsigned signed 의 크기는 같은걸 알 수 있다. 하지만 차이는 음수와 양수 차이를 알려주기 위하여 크기를 재어 보았다.

 

여기서 잠깐 sizeof 함수를 구현을 해보자. 물론 sizeof 함수를 편하게 제공하기 때문에 사용하기 쉽지만 비트 연산자를 좀 알아 보기 위하여 직접 구현 해보겠다.

 

void Ex2()

{

       signed char scData = 0;

       unsigned char uscData =~ 0;

 

       signed short int ssnData = 0;

       unsigned short int usnData =~ 0;

 

       signed int snData = 0;

       unsigned int unData =~ 0;

 

       signed long int slnData = 0;

       unsigned long int ulnData =~ 0;

 

       while(uscData != 0)

       {

             ++scData;

             uscData <<= 1;

       }

       while(usnData != 0)

       {

             ++ssnData;

             usnData <<= 1;

       }

       while(unData != 0)

       {

             ++snData;

             unData <<= 1;

       }

       while(ulnData != 0)

       {

             ++slnData;

             ulnData <<= 1;

       }

 

 

 

       printf("char Size of BitShift = %d bit\n",scData);

       printf("short int Size of BitShift  = %d bit\n",ssnData);

       printf("int Size of BitShift  = %d bit\n",snData);

       printf("long int Size of BitShift  = %d bit\n",slnData);

 

       printf("char sizeof() = %d BYTE\n",sizeof(char));

       printf("short int sizeof() = %d BYTE\n",sizeof(short int));

       printf("int sizeof() = %d BYTE\n",sizeof(int));

       printf("long int sizeof() = %d BYTE\n",sizeof(long int));

}

 

위를 실행 한 결과 아래와 같다.

 

 

보이는 화면은 Sizeof 와 직접 비트단위로 구현한 결과를 비교해보자

결과는 같은 걸 알 수 있다.  (1바이트는 8비트이다.)

 

~ 연산자는 자주 해 갈릴 수 있다. ~ 1의 보수 연산자 이다.

 

 

그럼 본격적으로 수치를 넘어서는 데이터의 연산을 진행 하자

 

 

먼저 덧셈 이다.

 

덧셈에서 중요한 건 unsigned long 변수를 사용할 건데 이 변수의 단위를 9자리 크기의 배열로 선언하여 각 배열들을 나열하여 표현하였다. 9개를 한 이유는 unsigned long 10자리 전체 크기를 고려하여 최대 9자리까지 표현하여 10자리는 자리 올림수로 파악하여 계산하였다. 직접 구현해보길 추천한다.

 

void Ex3()

{

       unsigned long A[] = {123456789, 987654321, 555554444, 333221000};

       unsigned long B[] = {        0, 123456789, 444445555, 111223333};

 

       unsigned long Limit = 1000000000;

       int nCarryValue = 0;

       int nSize = sizeof(A) / sizeof (unsigned long);

 

       printf("\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", A[i]);

       }

       printf("\n+\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", B[i]);

       }

       printf("\n");

       printf("======================================================\n");

 

 

       for(int i = nSize-1 ; i >= 0 ; i--)

       {

             if((B[i] == 0) && (nCarryValue == 0))

             {

                    continue;

             }

 

             A[i] = A[i] + B[i] + nCarryValue;

 

             if(A[i] < Limit)

             {

                    nCarryValue = 0;

             }

             else

             {

 

                    nCarryValue = A[i] / Limit;

 

                    A[i] = A[i] - Limit* nCarryValue;

                   

             }

 

       }

 

 

       printf("\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", A[i]);

       }

       printf("\n");

      

}

 

결과는 다음과 같다.


검산 해보았다 정확히 계산된다.  변수 하나로는 표현할 수 없는 데이터 크기이다.

 

다음으로는 뺄셈이다.

 

뺄셈 같은 경우에는 음수가 존재 하기 때문에 signed 로 하는 걸 잊지 말아라.

이건 덧셈 보다 더 쉽다. 캐리가 항상 1을 벗어나지 않기 때문에 ㅋ

한번 구현해보길 추천한다.

 

void Ex4()

{

       signed long A[] = {123456789, 987654321, 555554444, 333221000};

       signed long B[] = {        0, 123456789, 444445555, 111223333};

 

       signed long Limit = 1000000000;

       int nCarryValue = 0;

       int nSize = sizeof(A) / sizeof (signed long);

 

       printf("\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", A[i]);

       }

       printf("\n-\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", B[i]);

       }

       printf("\n");

       printf("======================================================\n");

 

 

       for(int i = nSize-1 ; i >= 0 ; i--)

       {

             if((B[i] == 0) && (nCarryValue == 0))

             {

                    continue;

             }

 

              A[i] = A[i] - B[i] - nCarryValue;

 

             if(A[i] > 0)

             {

                    nCarryValue = 0;

             }

             else

             {

                    nCarryValue = 1;

                    A[i] = A[i] + Limit;

             }

 

       }

 

 

       printf("\t");

       for(int i=0 ; i<nSize ; i++)

       {

             printf("%9u", A[i]);

       }

       printf("\n");

 

}

 

 

결과는 다음과 같다.

 

 

 

은근히 시간 많이 걸린다.
곱셈과 나눗셈은 다음 시간에 하겠다.