본문 바로가기

공부/c언어

부동소수점 [c언어]

반응형

참조

http://www.soen.kr/

18-1-라.부동 소수점

부호는 음 아니면 양이므로 1비트만 있으면 되고 지수부 8비트, 가수부 23비트로 구성되어 있다.

가수부가 길기 때문에 정밀도가 비교적 충분하고 지수부가 따로 있으므로 1038정도의 큰 수까지 표현할 수 있다.

물론 정밀도가 무한하지는 않기 때문에 수학에서의 실수처럼 소수점 이하 무한대까지를 기억하지는 못한다.

부동 소수점 방식은 한가지 큰 문제점이 있는데 같은 수를 표현하는 지수와 가수의 조합이 여러 벌 나올 수 있다는 점이다.

 

예를 들어 다음 수식들은 모두 12.345라는 실수값을 표현한다.

12.345*100, 1.2345*101, 0.12345*102, 123.45*10-1, 1234.5*10-2

같은 수를 표현하는 똑같은 방법이 여럿 존재하게 되면 두 변수의 상등 비교 연산을 하기가 까다로와진다. 그래서 한 수를 표현하는 방법은 하나만 존재하도록 정규화(Normalization)를 할 필요가 있는데 가수의 정수부를 한자리로 제한하면 12.345는 1.2345*101만 가능해진다. 즉, a.bcd*10n 식으로 소수점이 항상 가수의 첫 번째와 두 번째 사이에 있도록 하는 것이다.

 

이상은 10진수를 기준으로 한 부동 소수점 표현 방식인데 직관적인 이해를 위해 10의 거듭승을 사용했다. 실제 컴퓨터는 2의 거듭승으로 지수를 표현하고 가수도 이진수이므로 가수가 1~2사이의 수로 제한되어 가수는 항상 1.~~~~의 형태를 띠게 된다.

 

실수를 구성하는 각 요소가 어떻게 구성되고 해석되는지 요소별로 알아보자.

 

부호 : 부호는 음수 또는 양수 둘 중의 하나이므로 1비트만 있으면 된다. 0이 양수이고 1이 음수이다. 이 부호는 실수 자체의 부호만을 나타내며 지수의 부호는 아니다.

지수 : 지수를 n이라고 했을 때 가수부에 2n이 곱해진다. 음수 지수도 표현해야 하므로 지수는 자체에 부호를 따로 가져야 하는데 이때는 부호 비트를 따로 쓰지 않고 127의 바이어스를 적용한다.

지수의 길이는 8비트이므로 0~255까지의 범위를 가지며 바이어스 127을 적용하면 지수의 표현 범위는

-127~128까지이다.

최소 지수 -127과 최대 지수 128은 0과 무한대를 표현하는 특별한 용도로 예약되어 있다. 그래서 float형의 최대 표현 범위는 2127이며 대략 1038이 된다.

가수 : 23개의 비트로 구성되어 있으며 각 자리수에 2의 음수 거듭승으로 가중치가 부여되어 있다.

정규화 규칙에 의해 가수는 항상 이진수 1~2사이(1.~~~)여야 하며 이 규칙을 만족하기 위해 제일 왼쪽 비트(20자리)는 항상 1이라고 가정한다.

이 비트를 별도로 저장하지 않는 대신 정밀도는 2배 더 높아진다.

 

부호는 음 아니면 양이므로 1비트만 있으면 되고 지수부 8비트, 가수부 23비트로 구성되어 있다.

 가수부가 길기 때문에 정밀도가 비교적 충분하고 지수부가 따로 있으므로 1038정도의 큰 수까지 표현할 수 있다.

물론 정밀도가 무한하지는 않기 때문에 수학에서의 실수처럼 소수점 이하 무한대까지를 기억하지는 못한다.

부동 소수점 방식은 한가지 큰 문제점이 있는데 같은 수를 표현하는 지수와 가수의 조합이 여러 벌 나올 수 있다는 점이다.

 예를 들어 다음 수식들은 모두 12.345라는 실수값을 표현한다.

12.345*100, 1.2345*101, 0.12345*102, 123.45*10-1, 1234.5*10-2

같은 수를 표현하는 똑같은 방법이 여럿 존재하게 되면 두 변수의 상등 비교 연산을 하기가 까다로와진다. 그래서 한 수를 표현하는 방법은 하나만 존재하도록 정규화(Normalization)를 할 필요가 있는데 가수의 정수부를 한자리로 제한하면 12.345는 1.2345*101만 가능해진다.

즉, a.bcd*10n 식으로 소수점이 항상 가수의 첫 번째와 두 번째 사이에 있도록 하는 것이다.

 

이상은 10진수를 기준으로 한 부동 소수점 표현 방식인데 직관적인 이해를 위해 10의 거듭승을 사용했다. 실제 컴퓨터는 2의 거듭승으로 지수를 표현하고 가수도 이진수이므로 가수가 1~2사이의 수로 제한되어 가수는 항상 1.~~~~의 형태를 띠게 된다. 실수를 구성하는 각 요소가 어떻게 구성되고 해석되는지 요소별로 알아보자.

 

부호 : 부호는 음수 또는 양수 둘 중의 하나이므로 1비트만 있으면 된다. 0이 양수이고 1이 음수이다. 이 부호는 실수 자체의 부호만을 나타내며 지수의 부호는 아니다.

지수 : 지수를 n이라고 했을 때 가수부에 2n이 곱해진다.

음수 지수도 표현해야 하므로 지수는 자체에 부호를 따로 가져야 하는데 이때는 부호 비트를 따로 쓰지 않고 127의 바이어스를 적용한다.

지수의 길이는 8비트이므로 0~255까지의 범위를 가지며 바이어스 127을 적용하면 지수의 표현 범위는 -127~128까지이다.

 최소 지수 -127과 최대 지수 128은 0과 무한대를 표현하는 특별한 용도로 예약되어 있다.

그래서 float형의 최대 표현 범위는 2127이며 대략 1038이 된다.

가수 : 23개의 비트로 구성되어 있으며 각 자리수에 2의 음수 거듭승으로 가중치가 부여되어 있다.

정규화 규칙에 의해 가수는 항상 이진수 1~2사이(1.~~~)여야 하며 이 규칙을 만족하기 위해 제일 왼쪽 비트(20자리)는 항상 1이라고 가정한다.

이 비트를 별도로 저장하지 않는 대신 정밀도는 2배 더 높아진다.

가수의 제일 왼쪽 비트부터 1/2, 1/4, 1/8, 1/16의 가중치를 가지는 셈이며 이 비트들로부터 계산된 값에 1(20)을 더하면 실제 가수가 된다.

 

다음 실수는 십진수로 어떤 수인지 계산해 보자.

0 01111101 10000000000000000000000

부호가 0이므로 이 값은 일단 양수이다. 지수는 125인데 바이어스 127을 빼면 -2이다. 가수는 생략된 1과 첫 번째 비트의 가중치 1/2를 더하면 3/2이 된다. 가수의 제일 왼쪽에 1이 생략되어 있다고 볼 수 있으므로 실제 가수는 (1100000~)이다. 그래서 이 값은 다음과 같이 십진수로 바꿀 수 있다.

3/2 * 2-2 = 3/2 * 1/4 = 3/8 = 0.375

 

printf("80.504 = %d\n", 80.500f + 0.004f);

위를 수행하면

80.504 = 80.503988 <- 이렇게 결과가 나온다

왜 그런 걸까??

 

간단하게 생각해보면

1/3 = 0.333333~ 이렇게 나온다

0.3333333~ * 3 하면 0.99999999~

다시 1로 돌아오지 못한다....

 

컴퓨터의 계산 과정

1. 10진수 -> 2진수로 변환

2. 2진수로 곱셈 나눗셈 덧셈 뺄셈 계산한 후

3. 2진수 -> 10진수 변환

4. 10진수를 화면에 보여줌

 

위와 같은 과정을 거치므로 이런 결과가 나온다 ^^

 

 

반응형