[수치해석]
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"); } |
결과는 다음과 같다.
은근히 시간 많이 걸린다.
곱셈과 나눗셈은 다음 시간에 하겠다.
'[Public] 수학 > 수치해석' 카테고리의 다른 글
[Hermeneutics] 2. 피보나치 수열 (0) | 2009.10.06 |
---|---|
[Hermeneutics] 1. 최대공약수와 최소공배수 (0) | 2009.09.28 |