[ComputerScience bootcamp with python 3장]


본 포스팅은 컴퓨터사이언스 부트캠프 with 파이썬 이라는 책을 참고하여 개인 공부를 하면서 정리하고 있습니다.

문제 될 시 삭제하겠습니다.

Chapter 3 실수

실수 표현은 표현 범위가 넓은 대신 정밀도가 낮음

3-1. 실수 연산의 함정

a = 0.01
result = 0.0
for i in range(100):
	result += a

>>> result
1.0000000000000007

# 0.01을 100번 더했으니 1이 나오는 것을 예상했지만 아님

1에 매우 가까운 수라고는 해도 1은 아니다

이번에는 0.015625를 100번 더할 계획

계산결과 1.5625 라고 예상

a = 0.015625

>>> a
0.015625

result = 0.0
for i in range(100):
	result += a

>>> result
1.5625

# 이번에는 예측한 결과가 정확하게 나옴

이 결과를 이해하려면 컴퓨터가 실수를 표현하는 방법인 부동소수점이라는 개념을 알아야함


3-2. 부동소수점

ANSI/IEEE 754-1985라는 컴퓨터에서 부동 소수점 숫자를 나타내는데 사용하는 산업 표준

  • 여기서 ‘부’는 둥둥 떠다닌다는 의미

실수 123.456을 여러 가지 방식으로 표현한 것을 살펴보면

부동소수점

  • 소수점 위치를 보면 앞에 있기도 하고 뒤에 있기도 함
  • 소수점의 위치가 바뀌기 때문에 실수를 표현할 때 주로 사용

고정 소수점 방식보다 넓은 범위의 수를 표현할 수 있음


3-3. 단정도와 배정도

부동소수점에는 단정도 부동소수점과 배정도 부동소수점이 존재

  • 단정도
    • 실수를 32비트(4바이트)로 표현
    • 부호 1비트, 지수부 8비트, 가수부 23비트로 구성
  • 배정도
    • 실수를 64비트(8바이트)로 표현
    • 부호 1비트, 지수부 11비트, 가수부 52비트로 구성
    • 단정도보다 두 배 많은 만큼 정밀도가 높음
    • 파이썬은 배정도를 사용
      import sys
    
      >>> sys.float_info
      sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308,
      min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53,
      epsilon=2.220446049250313e-16, radix=2, rounds=1)
    
    • sys 모듈
      • 파이썬 인터프리터를 제어 할 수 있음 인터프리터: 소스 코드를 바로 실행하는 프로그램 또는 환경

    sys 모듈을 임포트한 다음 float_info를 입력하면 최댓값, 최솟값, 정밀도 등 확인 가능

  • 배정도 부동소수점으로 표현할 수 있는 가장 큰 수
>>> sys.float_info.max
1.7976931348623157e+308

여기서 e는 지수를 뜻함 exponent 줄임말

지수만 봐도 10의 308승이니 엄청나게 큰 수인걸 알 수 있음

1.7976931348623157 × 10^308

  • 배정도 부동소수점으로 표현할 수 있는 가장 작은 수
>>> sys.float_info.min
2.2250738585072014e-308

10의 -308승이 굉장히 작은지 알 수 있음

그만큼 8바이트 배정도 부동소수점을 사용하면 표현 범위가 엄청나게 넓어짐

2.2250738585072014 × 10^308


3-4. 1바이트 실수 자료형 설계

1바이트 실수 자료형을 수식으로 표현하면?

± 1.man × 2^exp - bias

1.man은 가수, 2는 밑수, exp-bias는 지수 의미

이 식을 이용해 7.75라는 10진수 실수를 1바이트 부동소수점으로 표현하면?

먼저, 2진수에 대한 식이므로 우선 7.75라는 10진수 실수를 2진수 실수바꾸는 작업을 먼저 해야 한다

3-4-1. 1바이트 실수 자료형 설계

10진수 실수를 2진수로 바꾸는 방법은 정수를 바꿨던 방법과 크게 다르지 않음

2^-1 은 음수가 아니라 분수 1/2, 2^-2 는 1/4

7.75 = 4 + 2 +1 + 0.5 + 0.25

= 22 + 21+ 20+ 2^-1+ 2^-2

= 111.11

3-4-2. 정규화

정규화란 소수점 왼쪽에 위치한 가수 부분을 밑수보다 작은 자연수가 되도록 만드는 것

예를 들어 10진수 567.89를 정규화하면?

  • 소수점 왼쪽에 위치한 가수 부분이 밑수 10보다 작은 자연수가 5가 되어 5.6789x10^2

  • 2진수의 밑수는 2

    • 2보다 작은 자연수는 1 만 존재
    • 소수점 왼쪽의 가수 부분은 항상 1이 됨

즉, 111.11을 정규화하면 111.11 = 1.1111 x 2^2


3-4-3. 메모리 구조

정규화된 부동소수점 수 1.1111 x 2^2을 앞의 수식과 비교해 보면?

  • man1111
  • exp - bias2

이제 1바이트의 메모리 구조를 정하고 manexp 값만 저장하면 설계는 끝남

이때, 지수부와 가수부에 할당하는 비트 수에 따라 표현 범위와 정밀도가 결정됨

1바이트 부동소수점이 어떻게 구성될까?

1바이트 부동소수점

  • 첫 번째 비트는 부호를 나타냄
    • 0이면 양수
    • 1이면 음수
  • 가운데 4비트는 지수부로 exp값 저장
  • 맨 뒤 3비트는 가수부로 man값 저장

이 때 bias는 지수의 부호를 결정하는데 쓰임

부동소수점의 지수부에는 부호 비트가 없으며 0~15의 양수만 나타낼 수 있음

하지만 음수 지수도 필요함

음수를 사용하려면 bias를 7로 두고 지수부(exp)에서 bias를 뺀 값을 실제 지수로 사용

bias2^n-1 - 1식에 지수부의 비트 수인 4를 대입

위의 3-4-2절에서 정규화된 수 1.1111x2^2에서 실제 지수는 2라는 의미는 exp-bias가 2라는 것

지수부의 비트 수 4를 식 2^n-1 -1에 대입해 얻은 bias 값이 7

실제로 부동소수점의 지수부에 나타나는 값 exp9

bias = 2^n-1 -1 = 7

exp - 7 = 2

exp = 9

필요한 값을 모두 구했으니 1바이트를 구성하면?

  • 부호 => 0
  • 지수부 => 1001
  • 가수부 => 1111

그치만 여기서 문제가 있는데 가수부는 3비트만 할당되는데 1111이다

이런 경우에는 뒷자리 1을 생략함

즉, 가수부는 111

0 1001 111 = 0100 1111 = 0x4f

실수 7.75는 1바이트 부동소수점으로 나타내면 0x4f

부동소수점을 계산할 때는 보수의 개념을 사용하지 않음


엡실론과 정밀도

엡실론(epsilon)

엡실론이란 1.0과 그 다음으로 표현 가능한 수 사이의 차이를 말하며, 이 엡실론은 실수들의 정밀도를 표현하는데 사용된다

배정도 실수 9.25를 부동소수점 방식으로 표현하면 1.00101 * 23 이다

위 식에서 지수 부분만 떼어 내 엡실론을 곱하면 이 실수와 다음 표현 가능한 수 사이의 차이를 구할 수 있음

import sys

ep = sys.float_info.epsilon
a = 9.25
diff = (2**3)*ep

>>> diff
1.7763568394002505e-15

b = a + diff
>>> b
9.250000000000002

epsilon은 1.0과 그 다음 수의 표현 가능한 수의 차이

따라서 위 식은 지수 부분이 1.0 * 20 이 아니라 (1.0) * 23 이므로 1.0 * 23 * epsilon을 해줘야

23 만큼 소수점이 움직인 epsilon을 구할 수 있음

위 식에서 diff는 지수 부분인 23 에 엡실론을 곱한 값으로 9.25와 그 다음 표현 가능한 수 사이의 차이

만약에 9.25diff보다 작은 값을 더하면 부동소수점 방식에서는 이 값을 다르게 표현 할 방법이 없다

예를 들어 9.25diff/2 더한 값과 9.25을 비교해도 두 값은 같다고 컴퓨터는 인식함

왜냐하면 표현 가능한 수의 차이 보다 작은 값을 더했기 때문에 컴퓨터가 인식하지 못하기 때문




© 2018. by Dev_Yonghee

Powered by Dev_Yong