본문 바로가기

Programming/C언어 초급

C언어 초급) 02.변수 : 04. 실수형

들어가며...

이번 글에서는 C언어의 변수 타입 중 실수형에 대해 알아보도록 하겠습니다.

실수는 익히 아시듯이 정수외에 소수부분까지 표현 가능한 자료형입니다. 또한 실수형은 부호 없는 수는 취급하지 않습니다. 이는 컴퓨터에서 실수형을 표현하는 방식에 기인합니다. 실수형의 표현방식과 실수형의 종류에 대해서 알아보도록 하겠습니다.

 

  • Table of Contents
    • 실수형 변수의 종류 및 길이
    • 실수형 변수의 표현 방법

실수형 변수의 종류 및 길이

실수형 변수의 종류는 크게 3가지이지만 대부분의 프로그래밍 언어에서는 float, double을 주로 사용하게 됩니다. 이에 대한 크기 및 표현 범위는 다음과 같습니다.

타입 크기(바이트) 표현범위
float 4   3.4 * 10^-38 ~ 3.4 * 10^38
double 8   1.7 * 10^-308 ~ 1.7 * 10^308
long double 10 ~ 16   1.2 * 10^-4932 ~ 3.4 * 10^4932

long double형은 프로그래밍 언어에 따라 지원하지 않는 경우도 있어 제외하고 표현범위를 보더라도 상상했던 값이랑 매우 상이함을 알 수 있습니다. 또한 정수의 표현범위와 비교하면 매우 큰 범위의 수를 표현함을 알 수 있습니다. 이는 실수형의 표현방식 때문입니다. 이러한 표현방식 때문에 실수형의 값은 우리가 생각한 값과 오차가 발생하게 됩니다.

실수형의 종류와 오차가 어떻게 발생하게 되는 지 아래 예제를 실행해 보시기 바랍니다.

 

● 예제코드

#include <stdio.h>

/**
 Main 함수
 */
int main(int argc, const char * argv[]) {
    float a = 123.456;
    
    // 실수형의 크기
    printf("The size of \'float\' = %lu\n", sizeof(float));
    printf("The size of \'double\' = %lu\n", sizeof(double));
    printf("The size of \'long double\' = %lu\n", sizeof(long double));
    
    // 1.1의 실제 출력 값
    printf("123.456 is %f\n", a);

    return 0;
}

 

● 결과확인

 

실수형 변수의 표현 방법

컴퓨터에서는 실수형을 표현하기 위해서 특정 규칙을 정해서 사용하고 있습니다. 이는 동일한 크기로 좀 더 많은 수를 표현하고 소수점 이하 표현 범위도(정밀도) 되도록 크게 표현하고자 만든 것입니다. 따라서, 위의 예제와 같이 사람이 생각하는 수와는 다소 다른 값을 출력하는 등 오차를 발생하기 때문에 이에 주의하여 사용하여야 합니다.

 

컴퓨터에서 실수의 표현 방식을 사람이 이해하기 위해서는 몇가지의 단계를 거쳐야 하는데 크게 실수(10진수 표현의...)를 "고정 소수점"  방식으로 변환한 후 이를 다시 "부동 소수점" 방식으로 변환하면 됩니다. 이러한 규칙을 정하여 표준으로 만들어 놨는데 IEEE 754 입니다.

 

● IEEE 754 표준

 

IEEE 754 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. IEEE 754는 IEEE에서 개발한 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준이다. ±0 등의 수와 무한, NaN 등의 기호를 표시하는 법과 이러한 수에 대한 �

ko.wikipedia.org

그럼 위의 예제에 사용했던 실수 123.456을 각각 고정 소수점, 부동 소수점 방식으로 변환하여 실제 메모리에 저장되는 값을 도출해 보도록 하겠습니다.

● 고정 소수점 표현방식

고정 소수점 방식은 소수점을 기준으로 정수와 소수를 각각 이진수로 표현하는 방식을 의미합니다. 정수와 소수를 이진수로 변환하는 방법은 정수부와 소수부에 따라 다른데 정수부는 2로 나누어 떨어질 때까지 반복적으로 나누면서 각각의 나눗셈 결과로 얻게되는 나머지값들을 나열하면 되며 소수부는 정수부를 구하는 방법의 거꾸로로 2로 곱하여 더이상 소수부가 없을 때까지 반복적으로 곱하면서 얻게되는 정수 부의 값들을 나열하면 됩니다.

고등학교 수학에서 모두 배운 것이나 말로 풀어쓰니 이해가 잘 안되리라 생각됩니다. 이를 단계적으로 그림으로 설명하기 전에 왜 이런 방식으로 표현되는 지 아래 그림부터 살펴보시기 바랍니다.

 

위의 그림과 같이 소위 직관적인 방법을 사용하면 각각의 비트에 값을 할당하여 각 비트의 합이 각각 정수부, 소수부의 값과 일치하게 하면 됩니다. 이러한 방법은 정수형 자료의 경우 유용하지만 소수부는 그림에서와 같이 값 자체가 점점 작아져 더한 값이 얼마인지 가늠하기가 어려워집니다.

 

그럼 이번에는 위에서 설명한 반복하여 2로 나누고 곱하는 방법을 사용하여 실제 표현하고자 했던 123.456을 고정 소수점으로 표현해보도록 하겠습니다.

 

정수부의 값은 결국엔 몫의 값이 1이 되기 때문에 문제가 없으나 앞서도 언급하였 듯이 소수부의 경우는 위의 예와 같이 아무리 2를 곱해도 0이 되지 않을 경우가 더 많기 때문에 컴퓨터에서 정확하게 표현되지 못하는 경우가 발생합니다.

지금까지 고정 소수점 표현방식에 대해서 알아봤습니다. 이제 이 고정 소수점 방식으로 변환된 값을 IEEE 754에 정의된 방법으로 부동 소수점 표현 방식으로 변경토록 해보겠습니다.

● 부동소수점 표현방식

프그래밍 언어에서 실수의 표현은 부동 소수점 방식을 사용한다고 하였습니다. 아래는 float, double의 경우 실수형 표현의 구조입니다.

  • 부호 비트 : 음수(1), 양수(0) 표현
  • 지수 부 : 실수값을 고정 소수점 방식의 이진수로 변환 후 a * 2^b 의 형태로 변환 했을 때 b의 값을 지수 부라 함
  • 가수 부 : 위의 a * 2^b 형태로 변환했을 경우 a의 값을 가수 부라 함

아직까지 지수 부와 가수 부의 정확한 의미를 이해하기 힘들어 보입니다. IEEE 745 위키사이트에서 제시하는 단계별로 123.456 값을 변환하는 방법을 살펴보도록 하겠습니다.

 

실제 프로그래밍에서는 메모리에 어떻게 할당되었는 지 확인해보도록 하겠습니다.

 

xcode의 디버깅을 통해 확인한 값은 0x79E9F642입니다. 이는 맥북이 little endian을 따르기 때문에 거꾸로 표현된 것이므로 실제의 값은 0x42F6E979 입니다.

위에 실제 계산한 값과 값이 좀 다릅니다. 이는 고정 소수점으로 변경 시 소수 부를 6번만 계산해서 그런 것입니다. 23비트로 표현할 수 있는 범위만큼 계산한다면 위와 같은 결과가 나올 것입니다.

마무리...

이번 글은 컴퓨터 공학 수업에서나 나올 법만 내용이 대부분이였습니다. 실수를 어떻게 표현하는 방법까지는 개발할 때는 굳이 필요 없는 지식일 수 있습니다. 다른 것은 몰라도 float(4바이트), double(8바이트)의 크기 만큼은 숙지 하시면 될 듯 합니다.

 


U2ful은 입니다. @U2ful Corp.