부동소수점
부동소수점(浮動小數點, floating point) 또는 떠돌이 소수점 방식은 실수를 컴퓨터 상에서 근사하여 표현할 때 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 것으로, 유효숫자를 나타내는 가수(假數)와 소수점의 위치를 풀이하는 지수(指數)로 나누어 표현한다.
컴퓨터에서는 고정 소수점 방식보다 넓은 범위의 수를 나타낼 수 있어 과학기술 계산에 많이 이용되지만, 근삿값으로 표현되며 고정 소수점 방식보다 연산 속도가 느리기 때문에 별도의 전용 연산 장치를 두는 경우가 많다. 고정 소수점과 달리 정수 부분과 소수 부분의 자릿수가 일정하지 않으나, 유효 숫자의 자릿수는 정해져 있다.
β를 밑으로 하는 k-부동소수점수 x는 다음 형태를 가진다.
여기서 formula_2인 정수이고, b는 formula_3인 정수이다. formula_4를 가수부라 하며, e는 지수부라고 한다. 만약 formula_5 혹은 formula_6이라면, 이 부동소수점수 x는 정규화되었다고 한다.
대부분의 컴퓨터에서 사용하는 이진법으로 정규화된 부동소수점수를 나타낸다면, 위 형태에서 β=2이고, 가수부는 0이나 1의 수로 채워진다. 이때 가수부 첫째 수는 1이다.
실제 컴퓨터에서는 보통 이진법을 사용하여 다음과 같이 세 부분의 값으로 실수를 나타낸다.예를 들어, 십진수 21.8125를 정규화된 이진수로 나타낸다고 해보자. 소수점 위의 (21.)=(10101)이고, 소수점 아래 (0.8125)=(11010)이다. 즉 (21.8125)=(10101.11010)이며, 이를 정규화하면 0.1010111010×2이다. 지수의 5를 이진법으로 바꾸면 101이다. 따라서, 32비트 정규화된 부동소수점수로 나타낸다면 맨 앞 비트의 부호는 0(양)이고, 지수부 부호는 0(양)이며, 지수부 나머지 6개 비트는 000101, 가수부는 101011101000…이 된다. 이것을 결합하면 (000001011010111010000000000000000)가
된다.
IEEE 754는 전기 전자 기술자 협회(IEEE)에서 개발한 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준이다.
IEEE 754의 부동 소수점 표현은 크게 세 부분으로 구성되는데, 최상위 비트는 부호를 표시하는 데 사용되며, 지수 부분(exponent)과 가수 부분(fraction/mantissa)이 있다.
−118.625 (십진법)을 IEEE 754 (32비트 단정도)로 표현해 보자.
이 결과를 정리해서 표시하면 다음과 같다.
부동 소수점 표현 방식은 수를 (가수)×(밑수)와 같이 유효숫자를 사용한 곱셈 형태로 표현한다. 예를 들어, -0.4를 밑수가 10인 부동 소수점으로 나타내면 -0.04×10이 되며 밑수가 2이면 -0.8×2가 되는데, 가수 부분을 한자리 자연수를 갖도록 바꾸면 -4×10과 같이 된다. 이처럼 가수의 첫째 자리가 밑수보다 작은 한자리 자연수가 되도록 바꾸는 것을 정규화라고 한다. 예를 들어, 앞의 값은 밑수가 2이면 -0.8×2이 되는데 이것을 정규화하면 -1.6×2이 된다. (여기서 볼 수 있듯이 밑수가 2일 때 정규화하면 가수부분의 첫째 숫자는 항상 1이 된다.)
컴퓨터 프로그래밍이나 전자계산기 등에서는 밑수가 10인 경우에 로마자 E 또는 e를 사용하여 함수 형태로 표시하기도 하는데, -0.4는 -0.04E+1 또는 -0.04e+1이 되며, 정규화하면 -4E-1 또는 -4e-1로 쓴다. 만약, 사용할 밑수를 미리 정해 놓는다면 가수와 지수만으로 실수를 표현할 수 있는데, 앞의 보기에서 밑수를 10으로 고정한다면 실수 -0.4는 가수 -4와 지수 -1의 조합으로 나타낼 수 있다. 보다 정형화된 형태로는 가수부와 지수부의 자릿수를 고정할 수 있는데, 만약 밑수는 10이고 부호는 따로 표시하며, 가수부 5자리, 지수부 3자리로 하는 형식이라면 앞의 값 -0.4는 '부호 -, 가수 40000, 지수 -005'로 나타낼 수 있다. 밑수가 2일 때에 정규화 결과 가수의 첫째 자리는 항상 1이 되므로 표시를 생략할 수 있다. 따라서, 고정된 형식에서 가수부에 1자리를 더 표시할 수 있게 되므로, 처리할 수 있는 유효숫자가 1자리만큼 늘어 난다. 앞의 예 1.6×2를 이 방식으로 표현하면 '부호 +, 가수 60000, 지수 -002'가 된다.
지수부에는 따로 부호 비트가 없기 때문에 음수 지수를 처리하기 위해 보통 바이어스 표현법을 사용한다. 즉, 할당된 자릿수로 표현 가능한 전체 영역을 반으로 나누어, 작은 영역에는 음수값 및 0, 큰 영역에는 양수값이 차례대로 1:1 대응되도록 한다. 예를 들어, 지수부를 8비트로 표현한다면 모두 256가지 수를 나타낼 수 있는데 이것을 반으로 나누어 음수 127개와 0, 양수 128개를 차례대로 대응시킨다. 따라서, 비트열 00000000은 지수 -127을 나타내고, 01111111은 지수 0, 11111111은 지수 128을 나타낸다. 일반적으로는 지수부가 n비트일 때 (2 / 2 - 1 = 2 - 1)을 지수 값에 더하며 이것을 바이어스 상수라고 한다. (다만, 지수부의 모든 자리가 모두 0 또는 1인 경우는 각각 0 또는 무한대를 나타내는 등 종종 특수한 목적으로 예약되어 있다.) 가수부에서는 정규화 결과 유효숫자의 첫째 자리는 언제나 1이므로 표시하지 않고, 소수 부분만 표현한다.
부동 소수점으로 표현한 수가 실수를 정확히 표현하지 못하고 부동 소수점 연산 역시 실제 수학적 연산을 정확히 표현하지 못하는 것은 여러가지 문제를 낳는다.
예를 들어, 0.1과 0.01을 표현하지 못하므로 0.1의 제곱이 0.01이 되지도 않고 0.01과 가장 가까운 수가 되지도 않는다. 24비트 단정밀도 표현에서, 십진수 0.1은 지수 = -4; 가수 = 110011001100110011001101 이고 그 값은,
이 수를 다시 제곱하면,
단정밀도 부동 소수점 (반올림 있는) 하드웨어에서 제곱을 한다면,
하지만 0.01과 가장 가까운 표현 가능한 실수는
또한, π (및 π/2)를 표현하지 못하므로 tan(π/2)가 무한대의 값이 나오지 않으며 오버플로(overflow)가 생기지도 않는다. 따라서 π/2를 정확히 표현하지 못하기 때문에 일반적인 부동소수점 하드웨어에서는 tan(π/2)를 계산하는 일이 불가능하다. C 언어에서 아래의 계산 결과는 16331239353195370.0 가 된다.
단정밀도에서는 (tanf 함수를 이용하여), −22877332.0 라는 결과를 얻는다.
같은 이유로 sin(π)는 0이 되지 않고 배정밀도에서 약 0.1225 또는 단정밀도에서 −0.8742가 된다.
부동소수점 덧셈과 곱셈은 모두 교환법칙 ("a" + "b" = "b" + "a" 이고 "a" × "b" = "b" × "a")이 성립하지만, 꼭 결합법칙이 성립하지는 않는다. 즉, ("a" + "b") + "c" 이 항상 "a" + ("b" + "c") 과 같지는 않게 된다.
예를 들면 7자리 부동소수점(Float 7) 10진수 계산을 할 때:
또한 항상 분배법칙이 성립하지도 않는다. 즉, ("a" + "b") × "c" 은 "a" × "c" + "b" × "c"과 다를 수 있다:
유효 숫자를 잃어버리는 문제 뿐만 아니라, π와 0.1를 정확하게 표현하지 못하는 문제와 다른 약간의 부정확성이 다음과 같은 현상을 일으킨다:
실제 사용되고 있는 부동 소수점 방식은 대부분 IEEE 754 표준을 따른다. 이 규격에서는 실수를 32비트로 처리하는 단정밀도(single precision)에서는 부호 1비트, 지수부 8비트, 가수부 23비트를 사용하며, 64비트로 처리하는 배정밀도(double precision)에서는 부호 1비트, 지수부 11비트, 가수부 52비트를 사용한다. 4배정도(quadruple precision)에서는 128비트로 부호 1비트, 지수부 15비트, 가수부 112비트를 사용한다.
과거의 마이크로소프트 제품은 자체 규격인 MBF(Microsoft Binary Format)를 사용했다. 이 형식에서는 배정밀도에서 부호 1비트, 지수 8비트, 가수 55비트를 사용하여 상대적으로 표현 범위가 좁은 대신에 유효숫자가 많으므로 보다 정밀한 값을 표현할 수 있다. 다만 실제 연산 과정에서는 IEEE 754 규격은 80비트 연산을 수행하므로, 연산 자체는 IEEE 754가 정밀하다.