2006년 7월 6일 목요일

C#과 떠다니는 소수점 이야기[1]

"C#의 음수 표현 방식에 대한 이야기"를 읽어본 독자들은 1바이트에 담긴 아름다움을 느끼실 수 있었으리라 생각합니다. (안 읽어봤다면 읽어보세요 클릭!)

이번에는 float과 double과 같은 부동 소수점(Floating Point) 자료형이 어떻게 구성되는가와 이들을 사용할 때 생각해야 되는 부분들에 대해 이야기를 나누고자 합니다.

다른 설명을 시작하기에 앞서 여러분이 한가지 알아둬야 할 것이 있습니다. 바로 10진수를 어떻게 2진수로 표현하는가입니다. 사실 이런 내용을 몰라도 프로그래밍을 잘하는 분들이 많습니다만 공부하는 데 돈이 드는 것도 아니니 조금 시간과 노력을 투자해서 알아둡시다. 게다가 별로 어렵지도 않습니다.

우선 정수를 2진수로 변환하는 방법은 수를 2로 나눠 나머지를 기록하고, 2보다 작은 수가 되어 더 이상 나눌 수 없을 때 계산을 종료하여 기록한 나머지를 밑에서부터 읽어나가는 것입니다.

예를 들어 123을 2진수로 표현하면 다음과 같습니다.

     몫    나머지
123   61    1
61    30    1
30    15    0
15    7     1
7     3     1
3     1     1
1     0     1

123(10진수) = 1111011(2진수)

어렵지 않죠? 이번엔 10진수의 소수를 2진수로 바꾸는 방법에 대해 설명하겠습니다.

소수를 2진수로 바꾸려면 해당 소수에 2를 곱해서 그 결과가 0보다 작으면 0을 기록하고, 1보다 크면 1을 기록한 뒤 결과의 정수 부분을 버리고 소수부분에 다시 2를 곱해 나가는 방식으로 계산하면 됩니다. 예로 10진수의 0.25를 2진수로 바꿔보겠습니다.
    
     결과    0보다큰가?   2진수
0.25  0.5    X           0.0
0.5   1.0    X           0.01 <-- 1.0의 정수 부분 1을 버리면 0만 남으므로 계산끝

또 다른 예를 들어볼까요? 이번에는 0.12를 2진수로 바꿔 보겠습니다.

     결과    1보다큰가?    2진수
0.12  0.24    X           0.0
0.24  0.48    X           0.01
0.48  0.96    X           0.000
0.96  1.92    O           0.0001    <-- 1.92에서 정수 부분 1을 버린다.
0.92  1.84    O           0.00011   <-- 1.84에서 정수 부분 1을 버린다.
0.84  1.68    O           0.000111   <-- 1.68에서 정수 부분 1을 버린다.
0.68  1.36    O           0.0001111  <-- 1.36에서 정수 부분 1을 버린다.
0.36  0.72    X           0.00011110
0.72  1.44    X           0.000111101 <-- 1.44에서 정수 부분 1을 버린다.
....

0.12는 끝이 안나는 군요. ^^; 0.12를 끝까지 계산해보진 않았지만, 만약 결과가 0이 되지 않는다면 끝임없이 2진수 변환을 진행하게 됩니다. 이것은 2진수가 가진 한계 때문입니다. 마치 분수 1/3을 소수로 표현하면 0.33333333333333333333333333333333333333...이 되는 것처럼 말이죠. 다행히도, float는 4byte, double은 8byte안에서 수를 표현해야 하므로 무한대로 계산하지는 않습니다. "부동 소수점 자료형의 "정밀도(Precision)"라는 속성이 어떤 것인지 좀 감이 잡히시죠?

... 다음에 계속 이어집니다. ( 이 포스트는 추후 수정될 수 있습니다.)

2006년 7월 3일 월요일

7월입니다!

벌써 7월달이 됐습니다. 2006년도 이제 꺾이기 시작하는군요.^^

요 근래에 약 8개월 동안 준비해온 BMT도 1위로 잘 끝내서 우리회사가 납품 대상자로 선정되되는 일이 있었고, C++ 원고도 마무리해서 출판사로 넘어갔습니다.
여전히 바쁘긴 하지만 큰 일들이 끝나서 그런지 심리적 여유가 조금은 생겨서 이것 저것 생각을 많이 하고 있습니다. 제일 많이 하는 고민은 "다음 포스트엔 어떤 글을 올릴까"이죠.(다음 C# 포스트는 "C#의 부동 소수점 이야기"가 될 것입니다.) ㅋㅋㅋ
그 다음 고민(?)들은 미리 이야기할 수 있는 것들이 아니라 지금 말씀 드리진 못하지만, 다음에 고민이 정리되는대로(궁금하죠? 별 거 없습니다. ㅋㅋ) 알려드리겠습니다.

어쨌거나 한주가 또 시작됐습니다. 모두들 즐프하세요! ^^

(아래는 글이 썰렁해서 넣어본 그림입니다. 제가 재작년에 슥슥 끄적여 놓은 게 컴터에 있더군요^^)


2006년 6월 29일 목요일

즐거운 주말 보내세요~

휴식이 기다리고 있는 주말이 하루 앞으로 다가 왔습니다.

이번 주말에는 시간을 좀 내서 서점에서 책을 좀 "구경"할까 합니다. 서점을 둘러보면 요즘 사람들이 어떤 것에 관심을 갖는지, 또 어떤 것을 필요로 하는지를 엿볼 수도 있고, 무엇보다 제가 읽을 책을 미리 점찍어둘 수도 있죠. (이젠 꽂아놓을 책장이 없어서 쌓아가고 있기 때문에 함부로 사지는 못합니다. ㅠ.ㅠ 이놈의 사재기병..)

근 몇달 동안 일에 치이느라 토요일도 일요일도 반납하고 살았는데, 모처럼 나들이를 하게 됐습니다. (비도 온다는데 대형 서점은 산책 코스로도 제격이죠 ㅋㅋㅋ)

모두들 남은 하루 화이팅 하시고, 즐거운 주말 맞이하시기 바랍니다. ^^

즐프!

2006년 6월 26일 월요일

C#의 음수 이야기

255

위 값은 C#에서 sbyte 형이 가질 수 있는 최대 값입니다. 이 값을 16진수와 2진수로 각각 변환하면 다음과 같지요. (한번 직접 계산해보세요^^)

16진수 : 7    F  
2진수  : 0111 1111

2진수를 한번 봅시다. 첫 번째 자리가 0입니다. 왜 첫 번째 비트가 0으로 비어있을까요? 그 비트를 사용한다면 더 큰 수를 담을 수 있을텐데 말이죠. 이 의문을 품고 다음 수를 16진수와 2진수로 바꿔 봅시다.

-1

16진수 : - 0    1  
2진수  : - 0000 0001

간단하네요. ^^ 그런데 이 값을 컴퓨터가 이해하게 하려면 어떻게 하죠? 컴퓨터가 '-' 기호를 이해할 수는 없습니다. 여러분도 잘 알고 있지만 컴퓨터는 0과 1만을 인식할 수 있을 뿐이죠.

컴퓨터 과학자들은 이 문제를 해결하기 위해 부호 비트(Sign Bit)라는 방법을 도입했습니다. 아까 255를 2진수로 변환한 값의 첫 번째 비트가 비어 있는 것을 봤죠? 그 첫 번째 비트가 바로 부호 비트로 사용되는 것입니다.

예를 들어 부호 비트가 1이면 음수, 0이면 양수가 되는 것이죠. 1000 0001 은 -1, 0000 0001은 +1입니다. 오, 훌륭하지 않나요? 이제 아름다운 음수를 비트 조합으로 표현할 수 있게 됐습니다. 그러나 여기에도 한가지 문제점이 존재합니다. 1000 0000 ( -0)과 0000 0000( +0)이 같이 존재한다는 것입니다.

음수를 표현하기 위해 제시된 또 하나의 방법은 1의 보수라는 방법입니다. 비트를 반전시켜 부호를 바꾸는 방식인데, 이 경우에도 -0, +0이 존재하는 문제는 마찬가지로 존재합니다. 앞의 방식보다 좋은 점이라면 0과 1의 비트를 뒤집는 연산은 엄청 빠르기 때문에 음수를 빨리 계산해 낼 수 있다는 것이죠.

컴퓨터 과학자들은 1의 보수가 가지는 단점을 보완하는 2의 보수라는 방법을 고안해 냈습니다. 비트를 반전시킨 다음 1을 더하는 것인데, 이렇게 하면 +와 -의 두가지 0이 존재하는 문제를 제거할 수 있습니다. -1을 2의 보수로 표현하면 다음과 같습니다.

1) 0000 0001 // 1
2) 1111 1110 // 모든 비트 반전
3) 1111 1111 // 반전된 비트에 1을 더하여 -1 표현. 16진수로 표현하면 FF

마지막 3)의 1111 1111이 2의 보수로 표현한 -1인 것입니다. 현대의 모든 컴퓨터는 2의 보수 방식을 이용하여 음수를 표현합니다. 그럼 다음의 코드를 한번 컴파일해서 실행해 보세요.

코드 :

  using System;
 
  class MainApp
  {
       static void Main(string[] args)
       {
           sbyte a = -1;
           Console.WriteLine("{0}, {0:X2}", a);
       }
  }

결과 :

-1, FF

재미있죠? 더 재미있는 이야기를 계속해 보겠습니다. 부호 비트로 사용하는 첫 번째 비트를 사용하면 더 큰 값을 표현할 수 있겠죠? 다음 코드에서 a는 16진수로 표현하면 FF, 2진수로 표현하면 1111 1111입니다.

byte a = 255;

똑같은 1111 1111인데 byte형 변수에 담기면 255가 되고 sbyte형 변수에 담기면 -1이 됩니다. 장난 하나 쳐 봅시다. 1111 1111을 갖는 byte형 변수의 값을 sbyte로 형변환 해서 실제로 -1이 되는 지를 보는 겁니다. 다음 코드를 컴파일하여 실행해 보세요.

코드 :

  using System;
 
  class MainApp
  {
       static void Main(string[] args)
       {
           byte a = 255;
           Console.WriteLine("{0}, {0:X2}", a);

           sbyte b = (sbyte)a;
           Console.WriteLine("{0}, {0:X2}", b);           
       }
  }

결과 :

255, FF
-1, FF

위 코드와 결과를 통해 알 수 있듯이, 부호가 있는 자료형과 그렇지 않은 자료형 사이에 값을 교환하는 일에는 주의를 기울여야 합니다.

이렇게 해서 C#에서 음수를 표현하는 방식과 주의해야 할 점에 대해 알아봤습니다. 앞으로도 클릭하세요 C# 2.0 프로그래밍에서는 미처 다루지 못한 이야기들을 종종 나누고자 합니다. 자주 찾아와 주세요. (방명록이 그냥 방치되어 있습니다. 방명록도 자주 이용해 주세요.^^;)

2006년 6월 23일 금요일

훈련 잘 다녀왔습니다.

동원 훈련 잘 받고 돌아왔습니다.

가서 그냥 아무 생각없이 지내다 와야겠다 하는 생각을 했는데 의외로 배운 것도 많고
좋은 사람들도 만날 수 있었습니다.

사실 통제하기 힘든 예비군들이 그렇게 달가운(?) 존재는 아니었을텐데, 중대장님, 행보관님, 소대장님 그리고 병사들이 정말 열심히 훈련을 도와줬습니다. (모두들 감사드립니다.) 정비 시간도 잘 써서 내무실(이젠 생활관이라고 하더군요)에 꽂혀 있던 책들도 몇 권 읽을 수 있었고, 무엇보다 밥도 맛있었습니다. 다소 투박하긴 하지만 우리 회사 구내식당보다 한 5배 정도는 더 맛있더군요.

병사들하고 이야기를 하면서 진로 이야기도 같이 하고 사회에 나올 것에 대한 준비도 좀 도와줄 수 있었으면 좋았을텐데, 시간이 허락되지 않아 좀 아쉽네요.

소모적인 시간이 될 수도 있었는데 유익하게 사용한 것 같아 뿌듯하네요 ^^

2006년 6월 19일 월요일

나를 채워야 할 때.

요즘 아침에 일어나면 아무것도 "해야 하는 일"이 없다는 사실이 너무 홀가분하고 좋습니다. VC++ 2005 원고를 탈고했기 때문에 새벽에 눈을 떴을 때 뭔가 해야한다는 압박에서 당분간 벗어나 지내게 됐습니다.(물론 회사 일은 회사 일대로 합니다만.)

지금도 자유로운 아침 시간이 잘 적응이 안되서 점심을 먹고 산책을 하면서 아침에 뭘 해야할까.. 하고 생각해 봤습니다. 여러가지가 생각이 나더군요. 몇가지 떠오른 생각은 다음과 같습니다.

- 다른 책을 집필한다.
  예) C#/C++ 코드 Recipes, 자료구조, 알고리즘, 데이터베이스 프로그래밍 등등...
- 소프트웨어를 개발한다.
  예) EAI용 메시지 버스, 데이터 기반의 워드 프로세서 등등...
- 잠을 잔다.
  ............ Good!!!!!!!
- 공부 한다.
 예) 영어, 메마른 정서를 적셔줄 시나 소설 읽기, 여행 하기,
      교양 물리나 사회 과학책 등 읽기.

책을 집필하거나 소프트웨어를 개발하는 것은 지금 시작해도 되긴 하지만, 그러기에는 지난 몇년간(특히 최근 1년간!!) 내 능력을 쏟아내기만 했지 나를 채우는 일은 못했다는 생각이 들더군요. 그래서 공부를 좀 하기로 했습니다.

한 3~4개월 정도가 걸리겠네요. 내 마음을 쉬게 하면서 또한 텅텅 비워진 마음과 머리 속에 지식과 지혜들을 담고자 합니다. 그렇게 공부하다가 새로운 일을 할만한 에너지가 생기고 또 목표가 생기면 일을 벌이려 합니다. 그 목표가 영어 실력이 될지, 새로운 책이 될지, 또는 소프트웨어가 될지는 모르겠지만, 마냥 공부만 하진 않을 것입니다.

공부도 즐거운 일이지만, 새로운 도전에 나서는 것만큼 재미있지는 않거든요 ^^

2006년 6월 17일 토요일

조국의 부름을 받고~~

이번주에는 예비군 훈련이 있어서 월요일과 금요일에는 서울 연구소(원래 제 근무지는 대전입니다.)에서 근무하고 화~목은 예비군 훈련을 받습니다.
조국의 부름을 받는 건 정말 영광스럽고 즐거운 일이 아닐 수 없습니다. ㅋㅋ (컴퓨터를 떠나 몇일을 지낸다는 것이 너무 좋네요)

예비군 훈련 기간동안 올라오는 질문에 대해서는 돌아와서 답변을 드리도록 하겠습니다. 이점 양해 부탁드립니다. ^^;