C :: 자료형의 범위를 구해보자. – 정수

long double 자료형의 범위를 구하겠다고 시작한 일이 쉽지만은 않네요. 그래서 쉬운 것부터, 정수형 자료형의 범위를 구하는 것부터 시작하였습니다.


처음에는 무작정 1씩 더해가는 방식으로 해봤습니다. 무지 비효율적입니다. OTL. 그 다음에 시도한 것은 pow() 함수를 이용하여 더해가는 방식을 사용했습니다. 멍청한 거죠? 그냥 pow() 함수로 구하면 되는 것을요. 그땐 왜 더한다는 생각만 했던지. 생각 해보니까 컴퓨터는 이진수를 다루기 때문에 더할 필요 없으니 2의 거듭승만 구하면 되겠더라구요. 하지만 pow() 함수도 비효율적입니다. 음수를 거듭제곱하면 양수가 되니까요.


그래서 마지막으로 사용한 방법이 비트 연산과 오버플로어를 이용한 것입니다. 쉬프트 연산을 말하는 거죠. 쉬프트 연산은 간단히 말해서 2배, 혹은 1/2배로 계산하지만 비트 단위로 연산하기 때문에 효율성에서 최고더라구요. 아래 코드를 볼까요?


/************************************************************************
 *  프로젝트 이름 : type in GCC                                           *
 *  프로젝트 목적 : GCC 컴파일러에서 자료형의 범위를 구한다.                    *
 *  소스파일 이름 : main.c                                                *
 ************************************************************************/

// 입출력을 위해  stdio.h를 부른다.
#include <stdio.h>

int main(void)
{
    int number = 1;
    int freq = 1;

    while(number > 0)
    {
        number <<= 1;
        printf("freq = %d, number = %d \n", freq++, number);
    }

    printf("\n이 자료형의 범위는 %d ~ %d 입니다. \n", number, ~number);

    return 0;
}


변수 number는 1단위씩 왼쪽 쉬프트 연산을 합니다. 즉, 2배씩 곱해지는 거죠. 이렇게 계속 쉬프트 연산을 하다가 number가 0보다 작거나 같을 때 연산이 중단됩니다. 0보다 작거나 같을 때를 조건으로 한 이유는 오버플로어 때문입니다. 직접 비트를 볼까요?


freq == 30 일 때, 01000000 00000000 00000000 00000000

freq == 31 일 때, 10000000 00000000 00000000 00000000

freq == 32 일 때, 00000000 00000000 00000000 00000000


쉬프트 연산을 31번 하면 음수가 되고, 32번하면 0이 되어 버립니다. “경고! 경고! 오버플로어 발생!” 이런 거죠, 뭐.


그리고 자료형의 범위를 출력할 때 따로 음수를 계산하지 않고 비트 연산자 ‘~’를 사용했습니다. 오버플로어가 된 상태를 보면, 음수입니다. 그것도 최소값이죠. 최대값에서 1을 더하면 최소값, 최소값에서 1을 빼면 최대값이 됩니다.


시계의 분침을 보면 59분에서 1분이 지나면 0분이 되죠. 만약 시계를 거꾸로 돌린다면 0분에서 59분이 되겠죠? 같은 원리입니다. 그래서 최소값은 number를 그대로 사용하고 최대값은 거꾸로 돌려 최대값을 표현할 수 있게 한 것입니다.


사용자 삽입 이미지

결과는 위와 같이 나왔습니다. 정확하게 오버플로어에서 멈추고 자료형의 범위도 나왔네요. short, int, long 모두 같은 방법으로 결과를 얻을 수 있습니다. long은 %d를 %ld로 바꿔야 하구요.


사용자 삽입 이미지

이건 unsigned 형의 결과입니다. 최소값이 0이므로 음수가 나와서는 안 되는데 음수가 나오고 최대값도 틀렸습니다. 와우, 머리 아퍼 OTL. 그런데 한 가지 이상한 게 있죠? 코드에서는 분명히…


    while(number > 0)
    {
        number <<= 1;
        printf("freq = %d, number = %u \n", freq++, number);
    }


이렇게 number가 0보다 작거나 같으면 멈추라고 명시했는데, 결과는 안 멈추고 0에서 멈췄습니다. 말이 안 되죠. 이건 내부적으로는 양수인데 보여준 건 음수로 보여줬다는 걸 의미합니다. 비트로 나타내면,


freq == 31 일 때, 10000000 00000000 00000000 00000000


unsigned 이라면, 저건 양수죠. 원인은 %d 때문이었습니다. unsigned의 %u를 안 쓴거죠. 제가 보는 교재에서는 %u를 조심하라고 나오던데, 반성해야겠습니다. 반성. 반성.


사용자 삽입 이미지

정확한 결과는 이렇습니다. 이제야 제대로 나오네요.


처음 C를 배울 때 비트 연산자란 것이 머리만 아프고 필요 없는 것인 줄 알았는데, 이번의 계기로 완전 중독 될 것 같습니다. 기계어와도 1:1 대칭 되어서 연산 속도도 빠르다네요. 다만, 아쉬운 건 정수 자료형에서만 가능하다는 것입니다. 실수에서는 안 되죠. 그래서 지금 머리가 좀 아픕니다. long double의 범위를 구해야 할텐데요. 에효.


Similar Posts

  • Ubuntu 에서 Mac OS X 로… 테마 변경

    http://sourceforge.net/projects/mac4lin/ 위 저장소에서 테마 패키지를 내려받아 압축을 푸신 후, “모양새 -> 테마” 에서 하나하나 설치하시면 됩니다. 이 패키지는 테마를 한번에 훅 설치해주는 게 아니라서 각 부분별로 개별적으로 설치해야 합니다. 그리고 적용하는 것도 “모양새 -> 테마 -> 사용자설정” 에서 따로따로 해야합니다. (처음에 설치해도 변경되는 게 없고 테마 목록에 새로 뜨는 것도 없어서 당황했던… ^^;) 터미널로 압축을…

  • imagEmail, GUI 구현

    GTK+와 Glade 3로 구현한 GUI입니다. 이제 여기에 C 코드로 알고리즘만 얹어 놓으면 됩니다. windowMain windowMain은 이름 그대로 메인 화면입니다. 오른쪽의 드롭다운 버튼으로 이메일의 서버종류를 선택할 수 있습니다. 우측 상단의 x 버튼으로 프로그램을 종료합니다. dialogSave dialogSave는 파일을 저장할 때 나오는 대화상자입니다. 아직 100% 구현되지 않았는데, 다 구현되면 “저장”, “취소” 버튼 위에 이메일 이미지가 어떻게 나오는지 보여줄…

  • imagEmail, 간략한 기획

    비주얼 베이직으로 만들었던 hisAlpha Image를 C 언어를 이용하여 리눅스용으로 다시 만들려고 합니다.  리눅스용이라고는 하나, 윈도우나 OS X용으로도 쉽게 포팅될 듯합니다. hiaAlpha Image는 일종의 프로토타입인 것이죠. 사실, 강분도 님의 권유가 아니었으면 그냥 묻혔을겁니다. ㅋ 아래는 간략한 기획입니다. 기능 이메일 주소를 이미지로 만듬. 15종의 메일서버 지원. 개발환경 환경: 리눅스 (Ubuntu 8.10, i386) 언어 및 툴킷 : C,…

  • 텍스트큐브 MT_Meta_RecentPS_Enhanced 플러그인 보완

    텍스트큐브용 MT_Meta_RecentPS_Enhanced 플러그인을 제 블로그에 적용해봤는데 아래 그림처럼 나왔습니다. 문제점을 간단히 요약하면, 글 제목의 스타일에 따라 썸네일의 아래에 빈 공간이 생길 수 있다. 이미지가 없는 글은 썸네일이 생성되지 않아 일관성을 해친다. 이렇습니다. 이런 문제점이 있다고 그냥 안 쓰기에는 너무나 아까운 플러그인이라서, 조금 손 보았지요. 우선, 썸네일이 출력되는 부분을 글 제목 아래로 내렸습니다. 이러면 글 제목…

  • 블로그(텍스트큐브) 서버를 직접 만들어보기 – OS & Package 설치

    지금 이 블로그는 제가 직접 만든 서버에서 열고 있습니다. 이전에 호스팅해주던 서버에 문제가 생겨서 결국 제가 직접 만들게 되었죠. 그러면서 삽질도 조금 해봤구요. Textcube 1.8텍스트큐브 1.8을 설치하기 위한 조건은 다음과 같습니다. 웹서버 Apache 1.2 이상 IIS 7 이상 (IIS 6는 비공식 지원) nginx 0.6.22 이상 lighttpd 1.4.22 이상 (베타 테스트 중) PHP PHP 5.2 이상…

  • 펜티엄 2에서의 작업환경

    이전 글에서 소개했듯이 제가 현재 사용중인 컴퓨터는 펜티엄 2입니다. 그런데 간혹 펜티엄 2에서는 (성능이 아닌 디스플레이를 따져서)작업하기가 너무 번거롭지 않냐라고 물어보는 사람이 있습니다. 아마 저사양 컴퓨터의 낮은 해상도를 생각한 모양입니다. 그래서 제 컴퓨터의 작업환경을 살짝 보여드릴까 합니다. 위 그림은 바탕화면을 찍은 것입니다. 해상도는 1440*900의 와이드입니다. 오잉? 펜티엄 2에서 저 해상도가 나와? 라고 하실 분이 계실…

0 Comments

  1. 네, 요즘 실수를 어떻게 비트로 표현하는지를 공부하고 있습니다. IEEE-754 표기법에 대해 검색하니 참고문헌들이 많이 나오네요. 고맙습니다.

  2. float, double 형에서 표현 가능한 수의 범위는 정수형에서처럼 간단한 비트연산만 가지고는 구하기 힘들 것 같네요. IEEE-754 표기법에서 비트들을 어떻게 나누어 실수를 표현하는지 찾아보시면 도움이 될 듯. ^^;

    ps. 텍스트큐브 포럼에 글 남기신 거 보다가 들어왔는데 마침 컴공 관련 글이 있어 남겨봅니다. ㅋㅋ

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다