[자바 무료 강의] └ [심화] 정수와 실수 - 코드라떼
Lesson List button
코스자바로 배우는 프로그래밍
hamburger button
강의└ [심화] 정수와 실수최종수정일 2022-01-25
아이콘미정

참고와 심화 내용이 있습니다. 강의를 진행하는 데는 필요 없으나 이후에 궁금하실 때 다시 보시면 좋습니다.

노트 강의

심화는 이후에 보셔도 상관없습니다.


목차


  1. 부호비트

  2. 정수부

  3. 음수는 어떻게 만드는 걸까?

  4. 실수의 정밀도는 무엇인가?

  5. 고정소수점방식과 부동소수점방식

  6. 32.21을 단정도(single precision) 부동소수점 방식으로 저장하는 법

  7. 32.21을 배정도(double precision) 부동소수점 방식으로 저장하는 법

  8. 부동소수점 데이터를 실수로 변경하는 법

1. 부호비트


부호비트

부호비트는 정수든 실수든 맨 앞의 1 bit를 부호비트로 가집니다. 0이면 양수이고 1이면 음수입니다.


2. 정수부


정수부

정수부는 정수를 표현하는 비트에서 부호비트를 제외한 나머지 비트를 정수부라고 하며 정수의 값을 표현하기 위한 비트로, 2진수로 구성되어있습니다


3. 음수는 어떻게 만드는 걸까?


image

컴퓨터는 가산기라는 것을 통해 더하는 연산만 할 수 있는데요. 32 - 32는 양수 32와 음수 32를 더하는 방식(32 + (-32))으로 감산을 할 수 있습니다. 32 - 32는 0이므로 양수 32를 0으로 만들 수 있는 bit를 만들기 위해 2의 보수를 만들었습니다.

예시로 양수 32에서 음수를 만드는 법은 다음과 같습니다

  1. 먼저 양수 32를 표현하는 비트를 이용하여 0은 1로 1은 0으로 반전시킵니다. 반전 시킨 값을 1의 보수라고 합니다.

  2. 1의 보수에 1을 표현하는 비트를 더합니다. 1의 보수에 1 비트를 가산한 것을 2의 보수라고 합니다.

양수 32를 나타내는 bit와 32의 2의 보수의 bit를 가산 연산하면 0 bit가 됩니다.


4. 실수의 정밀도는 무엇인가?


image


4-1. 정밀도

실제값과 저장된 값이 얼마나 정확한지를 나타내는 기준


4-2. 자릿수

앞의 숫자부터 세었을 때 수의 자리


4-3. 정밀도와 자릿수

자릿수까지 변수에 저장된 값을 보장하는 것을 정밀도라고 합니다.

즉, 정밀도 약 6~7자릿수라는 뜻은 6~7 자릿수 까지는 실제값과 동일하다라고 생각하시면 쉽습니다. 그 다음 자릿수 부터는 정확하지 않을 수 있다고 생각하시면 됩니다.

  • float 자료형은 약 정밀도 6~7자릿수(여섯에서 일곱 자릿수) 까지 보장합니다

  • double 자료형은 약 정밀도 15~16 자릿수(열 다섯에서 열 여섯 자릿수) 까지 보장합니다

자릿수가 범위인 이유는 저장된 값은 공식에 의해 실제값보다 더 근사할 수도 있고 덜 근사할 수도 있기 때문입니다. 그러므로 실수의 근사값을 더 정확히 보장하려면 정밀도가 높은 더 큰 범위의 자료형인 double 형을 사용하시는 것이 낫습니다.

그리고 가급적 오차가 중요하지 않을 때만 실수를 사용하는 것을 권장합니다.


5. [심화] 고정소수점방식과 부동소수점방식


5-1. 32 bit 고정소수점

고정소수점

고정소수점 방식은 값의 표현 범위를 넓히려면 그만큼 더 많은 비트를 가지고 있어야만 표현이 가능합니다. 예시로 32.125를 고정 소수점으로 표현하면 정수부 기준상 사용하지 않는 비트(0)가 낭비되며, 소수부를 표현할 수 있는 비트의 갯수가 고정됩니다. 결론적으로 큰 수일 수록 많은 메모리를 소모해야 하는 문제가 있기 때문에 부동소수점 방식을 사용합니다.


5-2. float(32bit) 부동소수점

float 부동소수점

32 bit 부동소수점 방식은 단정도(single precision) 라고 불립니다.

맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 8 bit, 가수부는 23 bit로 구성되어있으며

실수를 지수부와 가수부로 나누어 저장합니다.


5-3. double(64bit) 부동소수점

double 부동소수점

64 bit 부동소수점 방식은 배정도(double precision) 라고 불립니다.

맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 11 bit, 가수부는 52 bit로 구성되어있으며 실수를 지수부와 가수부로 나누어 저장합니다.


6. [심화] 32.21을 단정도(single precition) 부동소수점 방식으로 저장하는 법


실수 32.21이 단정도 방식(float, 32bit)으로 어떻게 bit로 변환되어 저장되는지 알아봅시다.


1. 32.21에서 정수 부분을 먼저 추출한다.

정수부분은 32이므로 32를 추출합니다.


2. 정수부분을 이진수로 변환한다.

32를 이진수로 표현하면 100000이 됩니다.


3. 소수부분의 값이 0이 될 때까지 또는 가수부 비트 수(23회) 이하까지 소수부분에 2를 곱하면서 이진수를 추출합니다.

먼저 소수부분을 추출하면 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가 됩니다.


4. 정수부의 2진수와 소수부분을 이진수로 변환한 것을 연결시킵니다.

100000.00110101110000101000111


5. 소수점을 맨 앞의 bit 전까지 이동시킵니다.

1.0000000110101110000101000111 (부동소수점이 앞으로 5칸이동)


6. 앞의 1 비트를 잘라냅니다.

0000000110101110000101000111


7. 비트수가 23(가수부 bit 수) 자릿수 까지만 저장합니다.

23 자릿수를 넘어간 bit는 잘라냅니다.

00000001101011100001010(2) (뒤의 00111 비트 잘라냄)


8. 5(부동소수점 이동 자릿수) + 127 (32bit Bias)를 계산합니다.

=132


9. 132를 이진수로 표기합니다.

10000100(2)


10. 계산된 비트를 연결합니다.

0(부호) 10000100(지수부) 00000001101011100001010 (가수부)

0 10000100 00000001101011100001010 (32bit)가 됩니다.


11. 32.21 실수를 bit로 표현하고 저장합니다.

01000010 00000000 11010111 00001010가 됩니다.


7. [심화] 32.21을 배정도(double precition) 부동소수점 방식으로 저장하는 법


실수 32.21이 배정도 방식(double, 64bit)으로 어떻게 bit로 변환되어 저장되는지 알아볼예정입니다.


1. 32.21에서 정수 부분을 먼저 추출한다.

정수부분은 32이므로 32를 추출합니다.

*단정도 방식과 동일합니다.


2. 정수부분을 이진수로 변환한다.

32를 이진수로 표현하면 100000이 됩니다.

*단정도 방식과 동일합니다.


3. 소수부분의 값이 0이 될 때까지 또는 가수부 비트 수(52회) 이하까지 소수부분에 2를 곱하면서 이진수를 추출합니다.

먼저 소수부분을 추출하면 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 가 됩니다.


4.정수부의 2진수와 소수부분을 이진수로 변환한 것을 연결시킵니다.

100000.0011010111000010100011110101110000101000111101011100


5. 소수점을 맨 앞의 bit 전까지 이동시킵니다.

1.000000011010111000010100011110101110000101000111101011100(부동소수점이 앞으로 5칸이동)


6. 앞의 1 비트를 잘라냅니다.

000000011010111000010100011110101110000101000111101011100


7. 비트수가 52(가수부 bit 수) 자릿수 까지만 저장합니다.

52 자릿수를 넘어간 bit는 잘라냅니다.

0000000110101110000101000111101011100001010001111010

(뒤의 11100 비트 잘라냄)


8. 5(부동소수점 이동 자릿수) + 1023 (64bit Bias)를 계산합니다.

=1028


9. 1028를 이진수로 표기합니다.

10000000100


10. 계산된 비트를 연결합니다.

0(부호) 10000000100(지수부) 0000000110101110000101000111101011100001010001111010 (가수부)

0 10000000100 0000000110101110000101000111101011100001010001111010 (64bit)가 됩니다.


11. 32.21 실수를 bit로 표현하고 저장합니다.

01000000 01000000 00011010 11100001 01000111 10101110 00010100 01111010가 됩니다.


8. [심화] 부동소수점 데이터를 실수로 변경하는 법


부동소수점 데이터를 실수로 변경하는 것은 어렵지 않습니다.

실수를 부동소수점 방식으로 바꾸는 과정의 역순과 비슷합니다.

단정도와 배정도가 방법은 동일하므로 단정도를 예시로 시작하겠습니다.

이전의 32.21을 32bit로 표현하면 01000010 00000000 11010111 00001010 였습니다.


1. 먼저 맨 앞의 부호 비트를 제거합니다.

0(부호비트)1000010 00000000 11010111 00001010


2. 지수부와 가수부를 나눕니다.

10000100(지수부) 0000000 11010111 00001010(가수부)


3. 지수부를 10진수로 변환합니다.

10000100 -> 132


4. 132(지수부 변환 10진수) - 127 (32bit Bias)를 계산합니다.

= 5 (부동소수점 이동해야하는 자릿수)


5. 가수부의 맨 앞에 1 bit를 붙입니다.

100000001101011100001010


6. 부동소수점을 맨 앞의 비트뒤에 둡니다.

1.00000001101011100001010


7. 부동소수점이 이동해야하는 자릿수가 5 이므로 부동소수점을 5칸뒤로 이동시킵니다.

100000.001101011100001010


8. 맨 앞의 bit부터 차례대로 계산하며 더합니다.

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을 저장후 다시 값을 읽을 때는 오차가 발생하게 됩니다.


9. 자바 언어에서는 최대정밀도 기준으로 반올림을 합니다.

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이 아닙니다.

도전자 질문
아이콘djfaksi(2022-05-07 22:09 작성됨)
실수에서 소수점 왼쪽에 정수부분은 소수부분이랑 길게 합쳐지고 23자리로 잘리기에 크기제한이 없는건가요? 정수 단일로 본다면 -21억에서 +21억까지 표현 가능한데 실수의 정수부분은 표현범위에 제한이 없는지 궁금합니다.
아이콘코드라떼(2022-06-06 14:25 작성됨)
안녕하세요. 코드라떼입니다 :)

실수의 정수 부분도 표현범위에 제한이 있을 수 있습니다.
32비트는 지수부가 8비트로 구성되고, 64비트는 지수부가 11비트로 구성되기 때문에 소수점이 이동될 수 있는 최댓값이 정해져 있습니다.
그러나 8비트로 표현될 수 있는 수가 255까지이며, 11비트는 2047입니다. 여기서 bias를 적용해도 굉장히 큰 값을 표현할 수 있음을 알 수 있습니다.

감사합니다 :)
아이콘djfaksi(2022-05-07 21:43 작성됨)
단정도 혹은 배정도 방식을 사용할 때 2진수의 정수부와 2진수의 소수부분을 합치고 맨 앞의 비트를 제거하는 이유가 있을까요? 
아이콘an(2022-04-14 22:19 작성됨)
bias를 더하는 이유는 연산이 2의 보수보다 적기 때문인가요?
혹시 다른 이유가 있을까요
아이콘코드라떼(2022-04-23 17:49 작성됨)
안녕하세요. 코드라떼입니다 :)

bias는 지수부의 자릿수를 지정함과 동시에 지수부의 양수와 음수를 표현하기 위한 기준입니다.
단정도의 경우 127의 값을 기준으로 하되 -126 ~ +127 지수를 가질 수 있습니다.
bias를 뺐을 때 음수의 값의 경우 음수 지수가 되며, 양수의 경우 양수 지수가 됩니다.

예시로 지수부의 자릿수가 2^-126 ~ 2^+127의 범위를 가질 수 있습니다.

감사합니다.
아이콘SweetPotato(2021-10-19 13:58 작성됨)
32의 이진수는 10000 이게 아니라 100000 공이 하나 더 있어여 하지 않나요?
아이콘코드라떼(2021-10-19 15:47 작성됨)
안녕하세요. 코드라떼입니다 :)

먼저 불편함을 드려 죄송합니다.

[심화] 32.21을 단정도 부동소수점 방식으로 저장하는 법
2. 정수부분을 이진수로 변환한다
32를 이진수로 표현하면 10000이 됩니다.

[심화] 32.21을 배정도 부동소수점 방식으로 저장하는 법
2. 정수부분을 이진수로 변환한다
32를 이진수로 표현하면 10000이 됩니다.

해당 부분의 10000 -> 100000이 맞습니다.
0이 하나 빠진 부분은 수정하였으며 연관된 다른 부분은 정상적으로 100000로 작성되어 있는 것을 확인했습니다.

감사합니다 :)
이용약관|개인정보취급방침
알유티씨클래스|대표, 개인정보보호책임자 : 이병록
이메일 : cs@codelatte.io
사업자등록번호 : 824-06-01921
통신판매업신고 : 2021-성남분당C-0740
주소 : 경기도 성남시 분당구 대왕판교로645번길 12, 9층 24호
파일
파일파일
Root
파일

해당 소스코드는 편집이 불가능합니다. 모르는 문법들이 있으므로 무시하셔도 됩니다. 다만 이 소스코드의 목적은 이진수로 표현되면 어떻게 표현되는지 보여주기 위함입니다.

Output
root$
Lesson List button
코스자바로 배우는 프로그래밍
hamburger button
강의└ [심화] 정수와 실수최종수정일 2022-01-25
아이콘미정

참고와 심화 내용이 있습니다. 강의를 진행하는 데는 필요 없으나 이후에 궁금하실 때 다시 보시면 좋습니다.

노트 강의

심화는 이후에 보셔도 상관없습니다.


목차


  1. 부호비트

  2. 정수부

  3. 음수는 어떻게 만드는 걸까?

  4. 실수의 정밀도는 무엇인가?

  5. 고정소수점방식과 부동소수점방식

  6. 32.21을 단정도(single precision) 부동소수점 방식으로 저장하는 법

  7. 32.21을 배정도(double precision) 부동소수점 방식으로 저장하는 법

  8. 부동소수점 데이터를 실수로 변경하는 법

1. 부호비트


부호비트

부호비트는 정수든 실수든 맨 앞의 1 bit를 부호비트로 가집니다. 0이면 양수이고 1이면 음수입니다.


2. 정수부


정수부

정수부는 정수를 표현하는 비트에서 부호비트를 제외한 나머지 비트를 정수부라고 하며 정수의 값을 표현하기 위한 비트로, 2진수로 구성되어있습니다


3. 음수는 어떻게 만드는 걸까?


image

컴퓨터는 가산기라는 것을 통해 더하는 연산만 할 수 있는데요. 32 - 32는 양수 32와 음수 32를 더하는 방식(32 + (-32))으로 감산을 할 수 있습니다. 32 - 32는 0이므로 양수 32를 0으로 만들 수 있는 bit를 만들기 위해 2의 보수를 만들었습니다.

예시로 양수 32에서 음수를 만드는 법은 다음과 같습니다

  1. 먼저 양수 32를 표현하는 비트를 이용하여 0은 1로 1은 0으로 반전시킵니다. 반전 시킨 값을 1의 보수라고 합니다.

  2. 1의 보수에 1을 표현하는 비트를 더합니다. 1의 보수에 1 비트를 가산한 것을 2의 보수라고 합니다.

양수 32를 나타내는 bit와 32의 2의 보수의 bit를 가산 연산하면 0 bit가 됩니다.


4. 실수의 정밀도는 무엇인가?


image


4-1. 정밀도

실제값과 저장된 값이 얼마나 정확한지를 나타내는 기준


4-2. 자릿수

앞의 숫자부터 세었을 때 수의 자리


4-3. 정밀도와 자릿수

자릿수까지 변수에 저장된 값을 보장하는 것을 정밀도라고 합니다.

즉, 정밀도 약 6~7자릿수라는 뜻은 6~7 자릿수 까지는 실제값과 동일하다라고 생각하시면 쉽습니다. 그 다음 자릿수 부터는 정확하지 않을 수 있다고 생각하시면 됩니다.

  • float 자료형은 약 정밀도 6~7자릿수(여섯에서 일곱 자릿수) 까지 보장합니다

  • double 자료형은 약 정밀도 15~16 자릿수(열 다섯에서 열 여섯 자릿수) 까지 보장합니다

자릿수가 범위인 이유는 저장된 값은 공식에 의해 실제값보다 더 근사할 수도 있고 덜 근사할 수도 있기 때문입니다. 그러므로 실수의 근사값을 더 정확히 보장하려면 정밀도가 높은 더 큰 범위의 자료형인 double 형을 사용하시는 것이 낫습니다.

그리고 가급적 오차가 중요하지 않을 때만 실수를 사용하는 것을 권장합니다.


5. [심화] 고정소수점방식과 부동소수점방식


5-1. 32 bit 고정소수점

고정소수점

고정소수점 방식은 값의 표현 범위를 넓히려면 그만큼 더 많은 비트를 가지고 있어야만 표현이 가능합니다. 예시로 32.125를 고정 소수점으로 표현하면 정수부 기준상 사용하지 않는 비트(0)가 낭비되며, 소수부를 표현할 수 있는 비트의 갯수가 고정됩니다. 결론적으로 큰 수일 수록 많은 메모리를 소모해야 하는 문제가 있기 때문에 부동소수점 방식을 사용합니다.


5-2. float(32bit) 부동소수점

float 부동소수점

32 bit 부동소수점 방식은 단정도(single precision) 라고 불립니다.

맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 8 bit, 가수부는 23 bit로 구성되어있으며

실수를 지수부와 가수부로 나누어 저장합니다.


5-3. double(64bit) 부동소수점

double 부동소수점

64 bit 부동소수점 방식은 배정도(double precision) 라고 불립니다.

맨 앞에는 +는 0이고 -는 1로 표시됩니다. 그리고 지수부는 11 bit, 가수부는 52 bit로 구성되어있으며 실수를 지수부와 가수부로 나누어 저장합니다.


6. [심화] 32.21을 단정도(single precition) 부동소수점 방식으로 저장하는 법


실수 32.21이 단정도 방식(float, 32bit)으로 어떻게 bit로 변환되어 저장되는지 알아봅시다.


1. 32.21에서 정수 부분을 먼저 추출한다.

정수부분은 32이므로 32를 추출합니다.


2. 정수부분을 이진수로 변환한다.

32를 이진수로 표현하면 100000이 됩니다.


3. 소수부분의 값이 0이 될 때까지 또는 가수부 비트 수(23회) 이하까지 소수부분에 2를 곱하면서 이진수를 추출합니다.

먼저 소수부분을 추출하면 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가 됩니다.


4. 정수부의 2진수와 소수부분을 이진수로 변환한 것을 연결시킵니다.

100000.00110101110000101000111


5. 소수점을 맨 앞의 bit 전까지 이동시킵니다.

1.0000000110101110000101000111 (부동소수점이 앞으로 5칸이동)


6. 앞의 1 비트를 잘라냅니다.

0000000110101110000101000111


7. 비트수가 23(가수부 bit 수) 자릿수 까지만 저장합니다.

23 자릿수를 넘어간 bit는 잘라냅니다.

00000001101011100001010(2) (뒤의 00111 비트 잘라냄)


8. 5(부동소수점 이동 자릿수) + 127 (32bit Bias)를 계산합니다.

=132


9. 132를 이진수로 표기합니다.

10000100(2)


10. 계산된 비트를 연결합니다.

0(부호) 10000100(지수부) 00000001101011100001010 (가수부)

0 10000100 00000001101011100001010 (32bit)가 됩니다.


11. 32.21 실수를 bit로 표현하고 저장합니다.

01000010 00000000 11010111 00001010가 됩니다.


7. [심화] 32.21을 배정도(double precition) 부동소수점 방식으로 저장하는 법


실수 32.21이 배정도 방식(double, 64bit)으로 어떻게 bit로 변환되어 저장되는지 알아볼예정입니다.


1. 32.21에서 정수 부분을 먼저 추출한다.

정수부분은 32이므로 32를 추출합니다.

*단정도 방식과 동일합니다.


2. 정수부분을 이진수로 변환한다.

32를 이진수로 표현하면 100000이 됩니다.

*단정도 방식과 동일합니다.


3. 소수부분의 값이 0이 될 때까지 또는 가수부 비트 수(52회) 이하까지 소수부분에 2를 곱하면서 이진수를 추출합니다.

먼저 소수부분을 추출하면 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 가 됩니다.


4.정수부의 2진수와 소수부분을 이진수로 변환한 것을 연결시킵니다.

100000.0011010111000010100011110101110000101000111101011100


5. 소수점을 맨 앞의 bit 전까지 이동시킵니다.

1.000000011010111000010100011110101110000101000111101011100(부동소수점이 앞으로 5칸이동)


6. 앞의 1 비트를 잘라냅니다.

000000011010111000010100011110101110000101000111101011100


7. 비트수가 52(가수부 bit 수) 자릿수 까지만 저장합니다.

52 자릿수를 넘어간 bit는 잘라냅니다.

0000000110101110000101000111101011100001010001111010

(뒤의 11100 비트 잘라냄)


8. 5(부동소수점 이동 자릿수) + 1023 (64bit Bias)를 계산합니다.

=1028


9. 1028를 이진수로 표기합니다.

10000000100


10. 계산된 비트를 연결합니다.

0(부호) 10000000100(지수부) 0000000110101110000101000111101011100001010001111010 (가수부)

0 10000000100 0000000110101110000101000111101011100001010001111010 (64bit)가 됩니다.


11. 32.21 실수를 bit로 표현하고 저장합니다.

01000000 01000000 00011010 11100001 01000111 10101110 00010100 01111010가 됩니다.


8. [심화] 부동소수점 데이터를 실수로 변경하는 법


부동소수점 데이터를 실수로 변경하는 것은 어렵지 않습니다.

실수를 부동소수점 방식으로 바꾸는 과정의 역순과 비슷합니다.

단정도와 배정도가 방법은 동일하므로 단정도를 예시로 시작하겠습니다.

이전의 32.21을 32bit로 표현하면 01000010 00000000 11010111 00001010 였습니다.


1. 먼저 맨 앞의 부호 비트를 제거합니다.

0(부호비트)1000010 00000000 11010111 00001010


2. 지수부와 가수부를 나눕니다.

10000100(지수부) 0000000 11010111 00001010(가수부)


3. 지수부를 10진수로 변환합니다.

10000100 -> 132


4. 132(지수부 변환 10진수) - 127 (32bit Bias)를 계산합니다.

= 5 (부동소수점 이동해야하는 자릿수)


5. 가수부의 맨 앞에 1 bit를 붙입니다.

100000001101011100001010


6. 부동소수점을 맨 앞의 비트뒤에 둡니다.

1.00000001101011100001010


7. 부동소수점이 이동해야하는 자릿수가 5 이므로 부동소수점을 5칸뒤로 이동시킵니다.

100000.001101011100001010


8. 맨 앞의 bit부터 차례대로 계산하며 더합니다.

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을 저장후 다시 값을 읽을 때는 오차가 발생하게 됩니다.


9. 자바 언어에서는 최대정밀도 기준으로 반올림을 합니다.

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이 아닙니다.

도전자 질문
아이콘djfaksi(2022-05-07 22:09 작성됨)
실수에서 소수점 왼쪽에 정수부분은 소수부분이랑 길게 합쳐지고 23자리로 잘리기에 크기제한이 없는건가요? 정수 단일로 본다면 -21억에서 +21억까지 표현 가능한데 실수의 정수부분은 표현범위에 제한이 없는지 궁금합니다.
아이콘코드라떼(2022-06-06 14:25 작성됨)
안녕하세요. 코드라떼입니다 :)

실수의 정수 부분도 표현범위에 제한이 있을 수 있습니다.
32비트는 지수부가 8비트로 구성되고, 64비트는 지수부가 11비트로 구성되기 때문에 소수점이 이동될 수 있는 최댓값이 정해져 있습니다.
그러나 8비트로 표현될 수 있는 수가 255까지이며, 11비트는 2047입니다. 여기서 bias를 적용해도 굉장히 큰 값을 표현할 수 있음을 알 수 있습니다.

감사합니다 :)
아이콘djfaksi(2022-05-07 21:43 작성됨)
단정도 혹은 배정도 방식을 사용할 때 2진수의 정수부와 2진수의 소수부분을 합치고 맨 앞의 비트를 제거하는 이유가 있을까요? 
아이콘an(2022-04-14 22:19 작성됨)
bias를 더하는 이유는 연산이 2의 보수보다 적기 때문인가요?
혹시 다른 이유가 있을까요
아이콘코드라떼(2022-04-23 17:49 작성됨)
안녕하세요. 코드라떼입니다 :)

bias는 지수부의 자릿수를 지정함과 동시에 지수부의 양수와 음수를 표현하기 위한 기준입니다.
단정도의 경우 127의 값을 기준으로 하되 -126 ~ +127 지수를 가질 수 있습니다.
bias를 뺐을 때 음수의 값의 경우 음수 지수가 되며, 양수의 경우 양수 지수가 됩니다.

예시로 지수부의 자릿수가 2^-126 ~ 2^+127의 범위를 가질 수 있습니다.

감사합니다.
아이콘SweetPotato(2021-10-19 13:58 작성됨)
32의 이진수는 10000 이게 아니라 100000 공이 하나 더 있어여 하지 않나요?
아이콘코드라떼(2021-10-19 15:47 작성됨)
안녕하세요. 코드라떼입니다 :)

먼저 불편함을 드려 죄송합니다.

[심화] 32.21을 단정도 부동소수점 방식으로 저장하는 법
2. 정수부분을 이진수로 변환한다
32를 이진수로 표현하면 10000이 됩니다.

[심화] 32.21을 배정도 부동소수점 방식으로 저장하는 법
2. 정수부분을 이진수로 변환한다
32를 이진수로 표현하면 10000이 됩니다.

해당 부분의 10000 -> 100000이 맞습니다.
0이 하나 빠진 부분은 수정하였으며 연관된 다른 부분은 정상적으로 100000로 작성되어 있는 것을 확인했습니다.

감사합니다 :)
이용약관|개인정보취급방침
알유티씨클래스|대표, 개인정보보호책임자 : 이병록
이메일 : cs@codelatte.io|운영시간 09:00 - 18:00(평일)
사업자등록번호 : 824-06-01921|통신판매업신고 : 2021-성남분당C-0740
주소 : 경기도 성남시 분당구 대왕판교로645번길 12, 9층 24호(경기창조혁신센터)
파일
파일파일
Root
파일

해당 소스코드는 편집이 불가능합니다. 모르는 문법들이 있으므로 무시하셔도 됩니다. 다만 이 소스코드의 목적은 이진수로 표현되면 어떻게 표현되는지 보여주기 위함입니다.

Output
root$