참고와 심화 내용이 있습니다. 강의를 진행하는 데는 필요 없으나 이후에 궁금하실 때 다시 보시면 좋습니다.
심화는 이후에 보셔도 상관없습니다.
ㅤ
ㅤ
부호비트는 정수든 실수든 맨 앞의 1 bit를 부호비트로 가집니다. 0이면 양수이고 1이면 음수입니다.
ㅤ
정수부는 정수를 표현하는 비트에서 부호비트를 제외한 나머지 비트를 정수부라고 하며 정수의 값을 표현하기 위한 비트로, 2진수로 구성되어있습니다
ㅤ
컴퓨터는 가산기라는 것을 통해 더하는 연산만 할 수 있는데요. 32 - 32는 양수 32와 음수 32를 더하는 방식(32 + (-32))으로 감산을 할 수 있습니다. 32 - 32는 0이므로 양수 32를 0으로 만들 수 있는 bit를 만들기 위해 2의 보수를 만들었습니다.
예시로 양수 32에서 음수를 만드는 법은 다음과 같습니다
먼저 양수 32를 표현하는 비트를 이용하여 0은 1로 1은 0으로 반전시킵니다. 반전 시킨 값을 1의 보수라고 합니다.
1의 보수에 1을 표현하는 비트를 더합니다. 1의 보수에 1 비트를 가산한 것을 2의 보수라고 합니다.
양수 32를 나타내는 bit와 32의 2의 보수의 bit를 가산 연산하면 0 bit가 됩니다.
ㅤ
ㅤ
실제값과 저장된 값이 얼마나 정확한지를 나타내는 기준
ㅤ
앞의 숫자부터 세었을 때 수의 자리
ㅤ
자릿수까지 변수에 저장된 값을 보장하는 것을 정밀도라고 합니다.
즉, 정밀도 약 6~7자릿수라는 뜻은 6~7 자릿수 까지는 실제값과 동일하다라고 생각하시면 쉽습니다. 그 다음 자릿수 부터는 정확하지 않을 수 있다고 생각하시면 됩니다.
float 자료형은 약 정밀도 6~7자릿수(여섯에서 일곱 자릿수) 까지 보장합니다
double 자료형은 약 정밀도 15~16 자릿수(열 다섯에서 열 여섯 자릿수) 까지 보장합니다
자릿수가 범위인 이유는 저장된 값은 공식에 의해 실제값보다 더 근사할 수도 있고 덜 근사할 수도 있기 때문입니다. 그러므로 실수의 근사값을 더 정확히 보장하려면 정밀도가 높은 더 큰 범위의 자료형인 double 형을 사용하시는 것이 낫습니다.
그리고 가급적 오차가 중요하지 않을 때만 실수를 사용하는 것을 권장합니다.
ㅤ
ㅤ
고정소수점 방식은 값의 표현 범위를 넓히려면 그만큼 더 많은 비트를 가지고 있어야만 표현이 가능합니다. 예시로 32.125를 고정 소수점으로 표현하면 정수부 기준상 사용하지 않는 비트(0)가 낭비되며, 소수부를 표현할 수 있는 비트의 갯수가 고정됩니다. 결론적으로 큰 수일 수록 많은 메모리를 소모해야 하는 문제가 있기 때문에 부동소수점 방식을 사용합니다.
ㅤ
32 bit 부동소수점 방식은 단정도(single precision) 라고 불립니다.
맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 8 bit, 가수부는 23 bit로 구성되어있으며
실수를 지수부와 가수부로 나누어 저장합니다.
ㅤ
64 bit 부동소수점 방식은 배정도(double precision) 라고 불립니다.
맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 11 bit, 가수부는 52 bit로 구성되어있으며 실수를 지수부와 가수부로 나누어 저장합니다.
ㅤ
실수 32.21이 단정도 방식(float
, 32bit)으로 어떻게 bit로 변환되어 저장되는지 알아봅시다.
ㅤ
정수부분은 32이므로 32를 추출합니다.
ㅤ
32를 이진수로 표현하면 100000이 됩니다.
ㅤ
먼저 소수부분을 추출하면 0.21입니다.
곱한 값이 1이 될 때 까지 반복해야 합니다.
0.21에 2를 곱하면 0.42가 됩니다.
소수부분이 0이 될 때까지 계속 값을 곱하면서 값이 1이 넘어가면 1을 감소시키고 다시 소수부분에 2를 곱하는 방식입니다.
1회 0.21 x 2 = 0.42 -> 0 (1을 넘지 않았으므로 0)
2회 0.42 x 2 = 0.84 -> 0 (1을 넘지 않았으므로 0)
3회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
4회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
5회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
6회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
7회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
8회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
9회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
10회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
11회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
12회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
13회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
14회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
15회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
16회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
17회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
18회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
19회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
20회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
21회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
22회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
23회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
23회까지 계산한 이진수를 표기하면 00110101110000101000111가 됩니다.
ㅤ
100000.00110101110000101000111
ㅤ
1.0000000110101110000101000111 (부동소수점이 앞으로 5칸이동)
ㅤ
0000000110101110000101000111
ㅤ
23 자릿수를 넘어간 bit는 잘라냅니다.
00000001101011100001010(2) (뒤의 00111 비트 잘라냄)
ㅤ
=132
ㅤ
10000100(2)
ㅤ
0(부호) 10000100(지수부) 00000001101011100001010 (가수부)
0 10000100 00000001101011100001010 (32bit)가 됩니다.
ㅤ
01000010 00000000 11010111 00001010가 됩니다.
ㅤ
실수 32.21이 배정도 방식(double
, 64bit)으로 어떻게 bit로 변환되어 저장되는지 알아볼예정입니다.
ㅤ
정수부분은 32이므로 32를 추출합니다.
*단정도 방식과 동일합니다.
ㅤ
32를 이진수로 표현하면 100000이 됩니다.
*단정도 방식과 동일합니다.
ㅤ
먼저 소수부분을 추출하면 0.21입니다.
배정도 방식은 가수부 비트 수가 52이므로 52회 까지 반복합니다.
*단정도 방식과 동일합니다.
1회 0.21 x 2 = 0.42 -> 0 (1을 넘지 않았으므로 0)
2회 0.42 x 2 = 0.84 -> 0 (1을 넘지 않았으므로 0)
— 반복구간
3회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
4회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
5회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
6회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
7회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
8회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
9회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
10회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
11회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
12회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
13회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
14회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
15회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
16회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
17회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
18회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
19회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
20회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
21회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
22회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
— 반복구간 종료
23회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
24회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
25회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
26회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
27회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
28회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
29회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
30회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
31회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
32회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
33회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
34회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
35회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
36회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
37회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
38회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
39회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
40회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
41회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
42회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
43회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
44회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
45회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
46회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
47회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
48회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
49회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
50회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
51회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
52회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
52회까지 계산한 이진수를 표기하면 0011010111000010100011110101110000101000111101011100 가 됩니다.
ㅤ
100000.0011010111000010100011110101110000101000111101011100
ㅤ
1.000000011010111000010100011110101110000101000111101011100(부동소수점이 앞으로 5칸이동)
ㅤ
000000011010111000010100011110101110000101000111101011100
ㅤ
52 자릿수를 넘어간 bit는 잘라냅니다.
0000000110101110000101000111101011100001010001111010
(뒤의 11100 비트 잘라냄)
ㅤ
=1028
ㅤ
10000000100
ㅤ
0(부호) 10000000100(지수부) 0000000110101110000101000111101011100001010001111010 (가수부)
0 10000000100 0000000110101110000101000111101011100001010001111010 (64bit)가 됩니다.
ㅤ
01000000 01000000 00011010 11100001 01000111 10101110 00010100 01111010가 됩니다.
ㅤ
부동소수점 데이터를 실수로 변경하는 것은 어렵지 않습니다.
실수를 부동소수점 방식으로 바꾸는 과정의 역순과 비슷합니다.
단정도와 배정도가 방법은 동일하므로 단정도를 예시로 시작하겠습니다.
이전의 32.21을 32bit로 표현하면 01000010 00000000 11010111 00001010 였습니다.
ㅤ
0(부호비트)1000010 00000000 11010111 00001010
ㅤ
10000100(지수부) 0000000 11010111 00001010(가수부)
ㅤ
10000100 -> 132
ㅤ
= 5 (부동소수점 이동해야하는 자릿수)
ㅤ
100000001101011100001010
ㅤ
1.00000001101011100001010
ㅤ
100000.001101011100001010
ㅤ
100000.001101011100001010
계산하는 방법은 다음과 같습니다.
1 x 2^5 -> 32 (자릿수가 5이므로 5부터 시작)
0 x 2^4 -> 0
0 x 2^3 -> 0
0 x 2^2 -> 0
0 x 2^1 -> 0
0 x 2^0 -> 0
0 x 2^-1 -> 0
0 x 2^-2 -> 0
1 x 2^-3 -> 0.125
1 x 2^-4 -> 0.0625
0 x 2^-5 -> 0
1 x 2^-6 -> 0.015625
0 x 2^-7 -> 0
1 x 2^-8 -> 0.00390625
…
이렇게 구한 값을 더하다보면 해당 값이 나옵니다.
32.118219490218475
그리고 비트 만큼 계산하여 더하면 해당 값이 나옵니다.
32.209999084472656
이렇게 32.21을 저장후 다시 값을 읽을 때는 오차가 발생하게 됩니다.
ㅤ
Java언어는 round to nearest ties away from zero방식으로 반올림을 합니다.
float
로 표현할 수 있는 수는 최대 정밀도는(오차없이 표현할 수 있는 수의 크기) 16777216 입니다.
즉 최대 정밀도는 7~8 자릿수로 예상됩니다.
32.209999084472656의 7 번째 자릿수를 기준으로 하면 32.209999 에서 반올림하게 됩니다.
반올림을 하면 32.21이 됩니다.
다만 출력을 할 때 32.21로 반올림을 할 뿐 실제로 저장된 데이터는 32.209999084472656 이므로 정확한 32.21이 아닙니다.
실수에서 소수점 왼쪽에 정수부분은 소수부분이랑 길게 합쳐지고 23자리로 잘리기에 크기제한이 없는건가요? 정수 단일로 본다면 -21억에서 +21억까지 표현 가능한데 실수의 정수부분은 표현범위에 제한이 없는지 궁금합니다.
안녕하세요. 코드라떼입니다 :) 실수의 정수 부분도 표현범위에 제한이 있을 수 있습니다. 32비트는 지수부가 8비트로 구성되고, 64비트는 지수부가 11비트로 구성되기 때문에 소수점이 이동될 수 있는 최댓값이 정해져 있습니다. 그러나 8비트로 표현될 수 있는 수가 255까지이며, 11비트는 2047입니다. 여기서 bias를 적용해도 굉장히 큰 값을 표현할 수 있음을 알 수 있습니다. 감사합니다 :)
단정도 혹은 배정도 방식을 사용할 때 2진수의 정수부와 2진수의 소수부분을 합치고 맨 앞의 비트를 제거하는 이유가 있을까요?
bias를 더하는 이유는 연산이 2의 보수보다 적기 때문인가요? 혹시 다른 이유가 있을까요
안녕하세요. 코드라떼입니다 :) bias는 지수부의 자릿수를 지정함과 동시에 지수부의 양수와 음수를 표현하기 위한 기준입니다. 단정도의 경우 127의 값을 기준으로 하되 -126 ~ +127 지수를 가질 수 있습니다. bias를 뺐을 때 음수의 값의 경우 음수 지수가 되며, 양수의 경우 양수 지수가 됩니다. 예시로 지수부의 자릿수가 2^-126 ~ 2^+127의 범위를 가질 수 있습니다. 감사합니다.
32의 이진수는 10000 이게 아니라 100000 공이 하나 더 있어여 하지 않나요?
안녕하세요. 코드라떼입니다 :) 먼저 불편함을 드려 죄송합니다. [심화] 32.21을 단정도 부동소수점 방식으로 저장하는 법 2. 정수부분을 이진수로 변환한다 32를 이진수로 표현하면 10000이 됩니다. [심화] 32.21을 배정도 부동소수점 방식으로 저장하는 법 2. 정수부분을 이진수로 변환한다 32를 이진수로 표현하면 10000이 됩니다. 해당 부분의 10000 -> 100000이 맞습니다. 0이 하나 빠진 부분은 수정하였으며 연관된 다른 부분은 정상적으로 100000로 작성되어 있는 것을 확인했습니다. 감사합니다 :)
해당 소스코드는 편집이 불가능합니다. 모르는 문법들이 있으므로 무시하셔도 됩니다. 다만 이 소스코드의 목적은 이진수로 표현되면 어떻게 표현되는지 보여주기 위함입니다.
참고와 심화 내용이 있습니다. 강의를 진행하는 데는 필요 없으나 이후에 궁금하실 때 다시 보시면 좋습니다.
심화는 이후에 보셔도 상관없습니다.
ㅤ
ㅤ
부호비트는 정수든 실수든 맨 앞의 1 bit를 부호비트로 가집니다. 0이면 양수이고 1이면 음수입니다.
ㅤ
정수부는 정수를 표현하는 비트에서 부호비트를 제외한 나머지 비트를 정수부라고 하며 정수의 값을 표현하기 위한 비트로, 2진수로 구성되어있습니다
ㅤ
컴퓨터는 가산기라는 것을 통해 더하는 연산만 할 수 있는데요. 32 - 32는 양수 32와 음수 32를 더하는 방식(32 + (-32))으로 감산을 할 수 있습니다. 32 - 32는 0이므로 양수 32를 0으로 만들 수 있는 bit를 만들기 위해 2의 보수를 만들었습니다.
예시로 양수 32에서 음수를 만드는 법은 다음과 같습니다
먼저 양수 32를 표현하는 비트를 이용하여 0은 1로 1은 0으로 반전시킵니다. 반전 시킨 값을 1의 보수라고 합니다.
1의 보수에 1을 표현하는 비트를 더합니다. 1의 보수에 1 비트를 가산한 것을 2의 보수라고 합니다.
양수 32를 나타내는 bit와 32의 2의 보수의 bit를 가산 연산하면 0 bit가 됩니다.
ㅤ
ㅤ
실제값과 저장된 값이 얼마나 정확한지를 나타내는 기준
ㅤ
앞의 숫자부터 세었을 때 수의 자리
ㅤ
자릿수까지 변수에 저장된 값을 보장하는 것을 정밀도라고 합니다.
즉, 정밀도 약 6~7자릿수라는 뜻은 6~7 자릿수 까지는 실제값과 동일하다라고 생각하시면 쉽습니다. 그 다음 자릿수 부터는 정확하지 않을 수 있다고 생각하시면 됩니다.
float 자료형은 약 정밀도 6~7자릿수(여섯에서 일곱 자릿수) 까지 보장합니다
double 자료형은 약 정밀도 15~16 자릿수(열 다섯에서 열 여섯 자릿수) 까지 보장합니다
자릿수가 범위인 이유는 저장된 값은 공식에 의해 실제값보다 더 근사할 수도 있고 덜 근사할 수도 있기 때문입니다. 그러므로 실수의 근사값을 더 정확히 보장하려면 정밀도가 높은 더 큰 범위의 자료형인 double 형을 사용하시는 것이 낫습니다.
그리고 가급적 오차가 중요하지 않을 때만 실수를 사용하는 것을 권장합니다.
ㅤ
ㅤ
고정소수점 방식은 값의 표현 범위를 넓히려면 그만큼 더 많은 비트를 가지고 있어야만 표현이 가능합니다. 예시로 32.125를 고정 소수점으로 표현하면 정수부 기준상 사용하지 않는 비트(0)가 낭비되며, 소수부를 표현할 수 있는 비트의 갯수가 고정됩니다. 결론적으로 큰 수일 수록 많은 메모리를 소모해야 하는 문제가 있기 때문에 부동소수점 방식을 사용합니다.
ㅤ
32 bit 부동소수점 방식은 단정도(single precision) 라고 불립니다.
맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 8 bit, 가수부는 23 bit로 구성되어있으며
실수를 지수부와 가수부로 나누어 저장합니다.
ㅤ
64 bit 부동소수점 방식은 배정도(double precision) 라고 불립니다.
맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 11 bit, 가수부는 52 bit로 구성되어있으며 실수를 지수부와 가수부로 나누어 저장합니다.
ㅤ
실수 32.21이 단정도 방식(float
, 32bit)으로 어떻게 bit로 변환되어 저장되는지 알아봅시다.
ㅤ
정수부분은 32이므로 32를 추출합니다.
ㅤ
32를 이진수로 표현하면 100000이 됩니다.
ㅤ
먼저 소수부분을 추출하면 0.21입니다.
곱한 값이 1이 될 때 까지 반복해야 합니다.
0.21에 2를 곱하면 0.42가 됩니다.
소수부분이 0이 될 때까지 계속 값을 곱하면서 값이 1이 넘어가면 1을 감소시키고 다시 소수부분에 2를 곱하는 방식입니다.
1회 0.21 x 2 = 0.42 -> 0 (1을 넘지 않았으므로 0)
2회 0.42 x 2 = 0.84 -> 0 (1을 넘지 않았으므로 0)
3회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
4회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
5회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
6회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
7회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
8회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
9회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
10회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
11회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
12회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
13회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
14회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
15회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
16회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
17회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
18회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
19회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
20회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
21회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
22회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
23회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
23회까지 계산한 이진수를 표기하면 00110101110000101000111가 됩니다.
ㅤ
100000.00110101110000101000111
ㅤ
1.0000000110101110000101000111 (부동소수점이 앞으로 5칸이동)
ㅤ
0000000110101110000101000111
ㅤ
23 자릿수를 넘어간 bit는 잘라냅니다.
00000001101011100001010(2) (뒤의 00111 비트 잘라냄)
ㅤ
=132
ㅤ
10000100(2)
ㅤ
0(부호) 10000100(지수부) 00000001101011100001010 (가수부)
0 10000100 00000001101011100001010 (32bit)가 됩니다.
ㅤ
01000010 00000000 11010111 00001010가 됩니다.
ㅤ
실수 32.21이 배정도 방식(double
, 64bit)으로 어떻게 bit로 변환되어 저장되는지 알아볼예정입니다.
ㅤ
정수부분은 32이므로 32를 추출합니다.
*단정도 방식과 동일합니다.
ㅤ
32를 이진수로 표현하면 100000이 됩니다.
*단정도 방식과 동일합니다.
ㅤ
먼저 소수부분을 추출하면 0.21입니다.
배정도 방식은 가수부 비트 수가 52이므로 52회 까지 반복합니다.
*단정도 방식과 동일합니다.
1회 0.21 x 2 = 0.42 -> 0 (1을 넘지 않았으므로 0)
2회 0.42 x 2 = 0.84 -> 0 (1을 넘지 않았으므로 0)
— 반복구간
3회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
4회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
5회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
6회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
7회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
8회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
9회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
10회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
11회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
12회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
13회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
14회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
15회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
16회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
17회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
18회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
19회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
20회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
21회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
22회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
— 반복구간 종료
23회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
24회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
25회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
26회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
27회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
28회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
29회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
30회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
31회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
32회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
33회 0.16 x 2 = 0.32 -> 0 (1을 넘지 않았으므로 0)
34회 0.32 x 2 = 0.64 -> 0 (1을 넘지 않았으므로 0)
35회 0.64 x 2 = 1.28 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
36회 0.28 x 2 = 0.56 -> 0 (1을 넘지 않았으므로 0)
37회 0.56 x 2 = 1.12 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
38회 0.12 x 2 = 0.24 -> 0 (1을 넘지 않았으므로 0)
39회 0.24 x 2 = 0.48 -> 0 (1을 넘지 않았으므로 0)
40회 0.48 x 2 = 0.96 -> 0 (1을 넘지 않았으므로 0)
41회 0.96 x 2 = 1.92 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
42회 0.92 x 2 = 1.84 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
43회 0.84 x 2 = 1.68 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
44회 0.68 x 2 = 1.36 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
45회 0.36 x 2 = 0.72 -> 0 (1을 넘지 않았으므로 0)
46회 0.72 x 2 = 1.44 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
47회 0.44 x 2 = 0.88 -> 0 (1을 넘지 않았으므로 0)
48회 0.88 x 2 = 1.76 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
49회 0.76 x 2 = 1.52 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
50회 0.52 x 2 = 1.04 -> 1 (1이상이므로 1을 감소시키고 이진수 1로 표기한다)
51회 0.04 x 2 = 0.08 -> 0 (1을 넘지 않았으므로 0)
52회 0.08 x 2 = 0.16 -> 0 (1을 넘지 않았으므로 0)
52회까지 계산한 이진수를 표기하면 0011010111000010100011110101110000101000111101011100 가 됩니다.
ㅤ
100000.0011010111000010100011110101110000101000111101011100
ㅤ
1.000000011010111000010100011110101110000101000111101011100(부동소수점이 앞으로 5칸이동)
ㅤ
000000011010111000010100011110101110000101000111101011100
ㅤ
52 자릿수를 넘어간 bit는 잘라냅니다.
0000000110101110000101000111101011100001010001111010
(뒤의 11100 비트 잘라냄)
ㅤ
=1028
ㅤ
10000000100
ㅤ
0(부호) 10000000100(지수부) 0000000110101110000101000111101011100001010001111010 (가수부)
0 10000000100 0000000110101110000101000111101011100001010001111010 (64bit)가 됩니다.
ㅤ
01000000 01000000 00011010 11100001 01000111 10101110 00010100 01111010가 됩니다.
ㅤ
부동소수점 데이터를 실수로 변경하는 것은 어렵지 않습니다.
실수를 부동소수점 방식으로 바꾸는 과정의 역순과 비슷합니다.
단정도와 배정도가 방법은 동일하므로 단정도를 예시로 시작하겠습니다.
이전의 32.21을 32bit로 표현하면 01000010 00000000 11010111 00001010 였습니다.
ㅤ
0(부호비트)1000010 00000000 11010111 00001010
ㅤ
10000100(지수부) 0000000 11010111 00001010(가수부)
ㅤ
10000100 -> 132
ㅤ
= 5 (부동소수점 이동해야하는 자릿수)
ㅤ
100000001101011100001010
ㅤ
1.00000001101011100001010
ㅤ
100000.001101011100001010
ㅤ
100000.001101011100001010
계산하는 방법은 다음과 같습니다.
1 x 2^5 -> 32 (자릿수가 5이므로 5부터 시작)
0 x 2^4 -> 0
0 x 2^3 -> 0
0 x 2^2 -> 0
0 x 2^1 -> 0
0 x 2^0 -> 0
0 x 2^-1 -> 0
0 x 2^-2 -> 0
1 x 2^-3 -> 0.125
1 x 2^-4 -> 0.0625
0 x 2^-5 -> 0
1 x 2^-6 -> 0.015625
0 x 2^-7 -> 0
1 x 2^-8 -> 0.00390625
…
이렇게 구한 값을 더하다보면 해당 값이 나옵니다.
32.118219490218475
그리고 비트 만큼 계산하여 더하면 해당 값이 나옵니다.
32.209999084472656
이렇게 32.21을 저장후 다시 값을 읽을 때는 오차가 발생하게 됩니다.
ㅤ
Java언어는 round to nearest ties away from zero방식으로 반올림을 합니다.
float
로 표현할 수 있는 수는 최대 정밀도는(오차없이 표현할 수 있는 수의 크기) 16777216 입니다.
즉 최대 정밀도는 7~8 자릿수로 예상됩니다.
32.209999084472656의 7 번째 자릿수를 기준으로 하면 32.209999 에서 반올림하게 됩니다.
반올림을 하면 32.21이 됩니다.
다만 출력을 할 때 32.21로 반올림을 할 뿐 실제로 저장된 데이터는 32.209999084472656 이므로 정확한 32.21이 아닙니다.
실수에서 소수점 왼쪽에 정수부분은 소수부분이랑 길게 합쳐지고 23자리로 잘리기에 크기제한이 없는건가요? 정수 단일로 본다면 -21억에서 +21억까지 표현 가능한데 실수의 정수부분은 표현범위에 제한이 없는지 궁금합니다.
안녕하세요. 코드라떼입니다 :) 실수의 정수 부분도 표현범위에 제한이 있을 수 있습니다. 32비트는 지수부가 8비트로 구성되고, 64비트는 지수부가 11비트로 구성되기 때문에 소수점이 이동될 수 있는 최댓값이 정해져 있습니다. 그러나 8비트로 표현될 수 있는 수가 255까지이며, 11비트는 2047입니다. 여기서 bias를 적용해도 굉장히 큰 값을 표현할 수 있음을 알 수 있습니다. 감사합니다 :)
단정도 혹은 배정도 방식을 사용할 때 2진수의 정수부와 2진수의 소수부분을 합치고 맨 앞의 비트를 제거하는 이유가 있을까요?
bias를 더하는 이유는 연산이 2의 보수보다 적기 때문인가요? 혹시 다른 이유가 있을까요
안녕하세요. 코드라떼입니다 :) bias는 지수부의 자릿수를 지정함과 동시에 지수부의 양수와 음수를 표현하기 위한 기준입니다. 단정도의 경우 127의 값을 기준으로 하되 -126 ~ +127 지수를 가질 수 있습니다. bias를 뺐을 때 음수의 값의 경우 음수 지수가 되며, 양수의 경우 양수 지수가 됩니다. 예시로 지수부의 자릿수가 2^-126 ~ 2^+127의 범위를 가질 수 있습니다. 감사합니다.
32의 이진수는 10000 이게 아니라 100000 공이 하나 더 있어여 하지 않나요?
안녕하세요. 코드라떼입니다 :) 먼저 불편함을 드려 죄송합니다. [심화] 32.21을 단정도 부동소수점 방식으로 저장하는 법 2. 정수부분을 이진수로 변환한다 32를 이진수로 표현하면 10000이 됩니다. [심화] 32.21을 배정도 부동소수점 방식으로 저장하는 법 2. 정수부분을 이진수로 변환한다 32를 이진수로 표현하면 10000이 됩니다. 해당 부분의 10000 -> 100000이 맞습니다. 0이 하나 빠진 부분은 수정하였으며 연관된 다른 부분은 정상적으로 100000로 작성되어 있는 것을 확인했습니다. 감사합니다 :)
해당 소스코드는 편집이 불가능합니다. 모르는 문법들이 있으므로 무시하셔도 됩니다. 다만 이 소스코드의 목적은 이진수로 표현되면 어떻게 표현되는지 보여주기 위함입니다.