[C++] 실수 표현
실수 표현
실수를 보관할 수 있는 타입들은
컴퓨터는 실수 또한 2진수 메모리 비트로 표현해야 합니다.
정수부는 변환하는 방법이 기존과 같고, 실수부는 다음과 같습니다.
- 절대 값이 1보다 작은 10진수 소수에 2를 곱한다.
- 2를 곱한 결과는 1을 넘는다면 1 0이라면 0으로 처리한 후 계산을 이어간다.
- 소수점 이하에 아무 숫자도 남지 않아 0이 됐다면 끝이다.
십진수 $0.75, 0.765625$일 경우 각각 이진수 $0.11, 0.10101$라는 결과가 나옵니다.
위에 계산한 이진수를 컴퓨터의 메모리로 표현하는 방법에 대표적인 것으로 고정 소수점 방식과 부동 소수점 방식으로 나눌 수 있습니다.
고정 소수점 표현 방식
고정 소수점(Fixed Point)은 정수 부분을 표현하는 비트 수와 소수를 표현하는 비트 수를 사전에 정한 후 해당 비트 수만을 이용하여 수를 표현하는 방식입니다.
고정 소수점은 소수부의 자릿수를 미리 정하고 고정된 자릿수의 소수를 표현하기 때문에 직관적입니다.
- 처음 1비트는 부호를 나타냅니다. 양수는 0 음수는 1입니다.
- 다음 15비트는 정수부를 나타냅니다.
- 다음 16비트는 소수부를 나타냅니다.
10진수 $5.75$를 이진수로 변환하고, 32비트 고정 소수점으로 표현해보면 다음과 같습니다.
고정 소수점의 장단점
장점은 크게 두가지가 있습니다.
첫 번째로 연산 효율성이 높습니다. 실수의 사칙연산은 정수보다 많은 연산을 필요로 하는데 고정 소수점의 정수부는 기존의 int형과 같은 정수 사칙연산을 사용하기 때문에 연산에 요구되는 시스템의 자원이 줄어듭니다.
두 번째로 적은 수의 비트를 사용한다는 것입니다. 행렬의 크기가 큰 행렬 연산이나 임베디드 시스템처럼 하드웨어 자원이 한정된 환경에서 8비트의 고정 소수점 방식을 사용한다면 크기를 크게 줄일 수 있습니다.
단점으로는 수를 표현함에 있어 정확도가 떨어진다는 것이 단점입니다.
정수를 표현하는 비트를 증가시키면 큰 수를 표현할 수 있으나 정밀한 숫자를 표현하는 것이 어려워지고, 소수를 표현하는 비트 수를 늘리면 정밀한 숫자를 표현할 수 있으나 큰 숫자를 표현할 수 없습니다.
부동 소수점 표현 방식
부동 소수점(Floationg Point)은 부동은 한자로 움직이지 않는다는 뜻의 부동(不動)이 아닌 부유하다는 의미를 가진 부동(浮動)입니다. 영어로는 소수점(point)이 둥둥 떠다닌다(floating)라는 의미로 소수점의 위치가 바뀐다는 것입니다.
부동 소수점 표현 방식은 고정 소수점 표현 방식과 비트를 사용하는 체계가 다르고, 이를 표현하는 다양한 체계 중 가장 널리 쓰이는 체계는 전기 전자 기술자 협회(IEEE)에서 개발해 제안된 IEEE 754입니다.
- 2진수를 정규화(normalize)합니다.
- 처음 1비트는 부호를 나타냅니다. 양수는 0 음수는 1입니다.
- 다음 8비트는 지수부를 나타냅니다. 정규화를 거친 값에 바이어스 값을 더한 값입니다.
- 다음 23비트는 가수부를 나타냅니다. 소수 부분의 값입니다.
10진수 $5.75$를 이진수로 변환하고, 32비트 부동 소수점으로 표현해보면 다음과 같습니다.
정규화
정규화란 2진수의 소수점을 이동시켜 소수점 앞에 1이 하나인 형태로 소수점을 이동시켜 표현한 것인데, $1.xxxx \cdots \times 2^n$ 형태로 지수화 해 나타내는 것입니다.
예시로 $5.75$를 2진수로 변환하면 $101.11_{(2)}$이고, 정규화를 진행하면 $1.0111_{(2)} \cdot 2^2$입니다.
여기서 지수는 2입니다.
지수부
정규화의 예시에서 얻은 지수 2를 바로 지수부에 채우면 될 것 같지만 그렇지 않습니다. IEEE754 표준에서 32비트로 실수를 표현할 때는 $127_{(10)}$이라는 바이어스 값을 더한 후 채우라고 돼있습니다. 즉 $129(2 + 127)$을 2진수로 변환해 $10000001_{(2)}$를 채웁니다.
바이어스 값은 지수가 음수일 경우 대처하기 위해 사용합니다. 예를 들어 $0.0101_{(2)}$라는 이진수 값이 나왔습니다. 이것을 정규화 하면 $1.01_{(2)} \times 2^{-2}$라는 값이 나옵니다.
이와 같은 경우 지수가 음수이므로 음수임을 알리는 부호 비트가 필요합니다. 하지만 이의 경우 표현할 수 있는 수의 범위가 작아진다는 큰 단점이 있고, 이를 보완하기 위해 8비트로 음수와 양수 모두를 표현하기 위한 장치로 바이어스 값을 두었습니다.
지수부의 값의 범위는 8비트이므로 256가지의 숫자를 표현 할 수 있고, 10진수로 바이어스 값에 의해 0 ~ 255가 됩니다.
127이 절반에 해당하는 숫자이므로 다음과 같습니다.
- 0 ~ 127 구간은 음수
- 128 ~ 255 구간은 양수
$0(00000000)_{(2)}$과 $255(11111111_{(2)})$는 각각 0과 무한대를 나타내기 위해 할당된 숫자이므로 앞선 정규화 방법이 적용되지 않습니다.
가수부
고정 소수점에서의 소수부 역할과 같고, 정규화 결과의 소수 부분이 들어갑니다.
부동 소수점의 장단점
장점으로는 다음과 같습니다.
부동 소수점은 고정 소수점에 비해서 더 큰 수의 범위를 표현 할 수 있습니다.
단점으로는 다음과 같습니다.
부동 소수점 자료형 처리는 고정소수점 자료형 처리에 비해 복잡한 연산이 필요하므로 컴퓨터 하드웨어의 성능을 표현할 때 부동 소수점 처리 능력이 빠지지 않습니다.
실수 연산이 부정확할 수 있다는 것이 가장 큰 단점입니다. 이는 컴퓨터 하드웨어가 가지는 본질적인 한계점 때문에 완벽하게 극복할 수는 없습니다.
소수 계산 오차
하지만 모든 십진수가 이진수로 깔끔하게 떨어지지는 않습니다.
예를 들어 0.2라는 값을 이진수로 변환한다면 0.001100110011…로 특정 수가 무한하게 반복됩니다.
부동 소수점이 아무리 큰 수를 표현 할 수 있다고 해도 메모리에 한계가 있어 무한대를 저장할 수 없으니 사용할 수 있는 메모리만큼의 소수를 집어넣고 근사치로 표현하게 됩니다.
근사치로 어떻게 표현을 할 것인지에 대한 기준으로 IEEE 754에서 정의한 방법은 다음과 같습니다.
- 가장 가까운 수로 반올림 (Round to nearest)
- 반올림 혹은 올림 (Round up, or round toward plus infinity)
- 반올림 혹은 버림 (Round down, or round toward minus infinity)
- 0으로 반올림하거나 절삭 (Round toward zero, or chop, or truncate)
짝수로 반올림과 큰 절대값으로 반올림은 주어진 수를 가장 가까운 정수로 반올림 할 때 사용되고, 소수 부분이 정확하게 0.5일 경우 어떻게 처리할지를 정의하는 규칙입니다.
가장 가까운 수로 반올림
절반을 자리올림하고, 나머지 절반은 자리내림 합니다. 즉 반올림을 하는 것이라고 생각하면 됩니다.
결과 값이 정확히 두 값의 가운데 위치할 때 최하위 비트가 홀수이면 더하기1, 짝수이면 잘라내는 것입니다.
이 방법은 항상 최하위 비트를 0으로 만들어줍니다.
반올림 혹은 올림
반올림하거나 최하위 비트의 값을 다음과 같이 변경합니다.
양수인 경우 0에서 먼 값, 음수인 경우 0에 가까운 값을 가집니다.
즉 항상 자리올림을 합니다.
반올림 혹은 버림
반올림하거나 최하위 비트의 값을 다음과 같이 변경합니다. 양수인 경우 0에 가까운 값, 음수인 경우 0에 먼 값을 가집니다.
즉 항상 자리내림을 합니다.
0으로 반올림하거나 절삭
특정 소수자리 이후의 수는 모두 잘라버립니다.
단정도와 배정도
단정도와 배정도라는 말로 자료형을 구분하는데, 단정도(Single-Precision) 자료형은 32bit float이며 위에서 살펴본 방식이다.
배정도(Double-Precision) 자료형은 64bit double을 말합니다.
배정도에서는 지수부가 11비트, 가수부가 52비트입니다.
지수부의 값의 범위는 11비트이므로 2048가지의 수를 표현할 수 있고, 배정도에서 바이어스 값은 1023이므로 0 ~ 1023가 됩니다.
1023이 절반에 해당하는 숫자이므로 다음과 같습니다.
- 0 ~ 1023 구간은 음수
- 1024 ~ 2047 구간은 양수
참조
https://developer.arm.com/documentation/dui0475/m/floating-point-support/ieee-754-arithmetic/ieee-754-arithmetic-and-rounding
https://arkainoh.blogspot.com/2017/11/fixed-point.html
https://gguguk.github.io/posts/fixed_point_and_floating_point/
https://eunajung01.tistory.com/116
댓글남기기