The Python Programming Language: Numerical Computation

수학적으로 자연수는 무수히 많은 원소를 가진다. 컴퓨터의 저장공간은 유한하므로 모든 수를 컴퓨터로 나타내는 것은 불가능하다.


Python에서 4바이트(8비트=1바이트) int-type은 $-2147483648$에서 $2147483647$까지 표현 할 수 있다. 8 비트를 사용하면 8개의 0과 1을 결합하는 $2^8 = 256$가지의 방법이 있으므로, 256개의 자연수를 나타낼 수 있다. 예를 들어, $-127$에서 $+128$사이의 256개의 정수를 나타낼 수 있다.


이것으로 정수가 컴퓨터에서 어떻게 표현되는지 알 수 있다. 사용된 바이트 수에 따라 최솟값과 최댓값 사이의 정수를 나타낼 수 있다. 컴퓨터에서 4바이트 또는 8바이트를 사용하여 하나의 정수를 표현하는 것이 일반적이며 4바이트의 경우 위에서 보인 바와 같이 $-2147483648$ 및 $+2147483647$의 최소 및 최댓값을 정확히 나타내며 8바이트의 경우 최대 정수는 $+9223372036854775807$이다 ($\approx 9.2\cdot 10^{18}$).


이제 부동 소수점 숫자는 컴퓨터에서 어떻게 나타내는지 알아보겠다. 모든 실수 $x$는 $x=a\cdot 10^b$($a, b$는 정수)로 표현할 수 있다. 여기서 $a$를 가수, $b$를 지표라고 한다. 그러므로 모든 실수는 2개의 정수를 이용하여 표현할 수 있다.


IEEE-754 표준은 하나의 부동소수점 숫자에 8바이트를 사용한다. 이 64비트중 54비트는 가수 $a$, 10개의 비트는 지표 $b$를 표현하는데 사용한다. 이것이 부동 소수점 숫자가 저장되는 방식이다(실제로는 조금 더 복잡하다).


실제로 일상생활에서 $10^{300}$을 넘는 숫자를 사용하지 않는다. 따라서 컴퓨터에서 부동 소수점 숫자는 우리가 일반적으로 필요로 하는 숫자의 범위를 나타내고 있다. 그러나 과학적 계산에서 부동 소수점의 범위를 초과할 수 있는 (종종 중간 결과에서) 작은 숫자와 큰 숫자가 사용된다는 경고를 받는다.


부동 소수점 숫자의 범위를 초과할 위험이 있는 경우, 우리는 방정식을 재조정해야 한다. 모든 숫자가 대략 1이 되도록 방정식을 재조정하면 코드를 디버깅하는 데도 유용하다. 1보다 훨씬 크거나 작은 숫자가 나타나는 경우 이는 오류를 나타내는 것일 수 있다.

부동소수점 사용

부동 소수점 숫자가 표현되는 방식으로 인해 또 다른 복잡성이 있다. 모든 부동 소수점 숫자가 컴퓨터에서 정확하게 표현될 수 있는 것은 아니다. 숫자 $1.0$은 정확하게 나타낼 수 있지만, 숫자 $0.1$, $0.2$ 및 $0.3$은 나타낼 수 없다.


대신 실수에 "가장 가까운" 부동 소수점 숫자가 선택된다. $0.1$은 $0.10000000000000001$, $0.3$은 $0.29999999999999999$ 이다. 따라서 이로 인해 문제가 발생할 수 있다. x가 $0.1, 0.2, \dots, 0.9, 1.0$ 을 가지는 반복문을 만들때 다음과 같이 할 수 있다.


x = 0.0
for i in range(1,11):
	x = x + 0.1
    print("x=%19.17g" %(x))

그러나 이 프로그램의 결과는 아래와 같다.


x=0.10000000000000001
x=0.20000000000000001
x=0.30000000000000004
x=0.40000000000000002
x=                0.5
x=0.59999999999999998
x=0.69999999999999996
x=0.79999999999999993
x=0.89999999999999991
x=0.99999999999999989

변수 x가 정확히 $1.0$의 값을 갖지 않기 때문에 이다. 따라서 절대로 두 부동 소수점 숫자를 비교하면 안된다. 두 개의 부동 소수점 숫자 사이의 거리를 비교하여 해결할 수 있다.


x = 0.0
while abs(x - 1.0) > 1e-8:
  x = x + 0.1
  print("x=%19.17g" %(x))

위 예제와 유사하게 정수에 대해 반복하여 정수에서 부동 소수점 수를 계산할 수 있다.


for i in range(1, 11):
  x = i * 0.1
  print("x=%19.17g" % (x))

이 프로그램의 결과를 살펴볼 필요가 있다.


x=0.10000000000000001
x=0.20000000000000001
x=0.30000000000000004
x=0.40000000000000002
x=                0.5
x=0.60000000000000009
x=0.70000000000000007
x=0.80000000000000004
x=0.90000000000000002
x=                  1

위의 프로그램 결과와 비교하면 부동 소수점 숫자가 서로 다른 것을 알 수 있다. 이것은 수치 계산에서 $0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 1.0$이 아니라는 것을 의미한다.

반응형