2.2 부동소수점 실수 자료형

정수와 실수 자료형

파이썬에서는 정수(integer)뿐 아니라 소숫점을 포함하는 실수(real number)도 다룰 수 있다. 정수 데이터에는 소숫점이 없고 실수 데이터에는 소수점이 붙어 있다.

10  # 정수
10
10.0  # 실수
10.0

정수부가 0인 실수는 0을 생략할 수 있다.

.1  # .1 = 0.1
0.1

숫자 계산을 하는 경우 계산에 쓰인 숫자 중 하나라도 소숫점이 있는 실수가 있으면 계산결과는 실수가 된다. 나눗셈 연산의 결과는 입력에 상관없이 항상 실수로 처리한다. 예를 들어 \(10 \times 5\)는 정수로 취급하지만 \(10.0 \times 5\)\(10 \div 5\)는 실수로 취급한다.

10 * 5  # 정수
50
10.0 * 5  # 실수
50.0
10 / 5  # 실수
2.0

정수와 실수는 컴퓨터 메모리에 저장되는 방식이 다르다. 이를 데이터의 자료형(type)이 다르다고 한다. 파이썬에서 정수는 int라는 정수 자료형으로 처리한다. 실수는 float라는 부동소수점(floating point number) 자료형으로 처리된다. 파이썬에서 데이터의 자료형을 알려면 type 명령을 사용한다.

type(10)
int
type(10.0)
float

부동소수점 실수

프로그래밍 언어는 IEEE 754라는 국제표준에 따라 실수를 부동소수점 방식으로 표현한다. 부동소수점 방식에서는 숫자를 정수로 된 유효숫자와 정수로 된 지수의 곱으로 표현한다. 예를 들어 십진수 부동소수점 방식에서 \(123.456\)이란 숫자는 \(123456 \times 10^{-3}\) 이므로 \(123456\)이라는 정수 유효숫자와 \(-3\)이라는 정수 지수로 나타낼 수 있다.

파이썬에서는 유효숫자e지수 라는 방법으로 부동소수점 형태를 직접 표현한다.

\[ \text{유효숫자}e\text{지수} = \text{유효숫자} \times 10^{\text{지수}} \]
123e2  # 123e2 = 123.0 x 100 = 12300.0
12300.0
123e-2  # 123e-2 = 123.0 x 0.01 = 1.23
1.23
123.456e-3  # 123.456e-3 = 123.456 x 0.001 = 0.123456
0.123456

연습 문제 2.2.1

유효숫자e지수 표현법으로 되어 있는 다음 숫자를 보통의 소숫점 표현으로 나타내라.

  1. 5e8

  2. 5.6e3

  3. -2.1e2

  4. -3.4e-1

연습 문제 2.2.2

다음 숫자를 유효숫자e지수 표현법으로 나타내라. 유효숫자는 정수가 되어야 한다.

  1. 3.141592

  2. 2.718

  3. 1.4

  4. 1.73

십진법과 이진법

컴퓨터는 십진법이 아닌 이진법을 사용한다. 십진법에서는 0, 1, 2, 3, 4, 5, 6, 7, 8, 9의 10개 숫자만 사용하고 10 이상의 수는 \(10, 100, 1000, 10000, \ldots\) 자리를 나타내는 숫자를 나열하여 표현한다. 따라서 모든 십진법 숫자는 10의 제곱의 합으로 풀어서 나타낼 수 있다.

\[\begin{split} \begin{eqnarray} 12 &=& & & 10 &+& 2 &=& & & 1 \times 10^1 &+& 2 \times 10^0 \\ 123 &=& 100 &+& 20 &+& 3 &=& 1 \times 10^2 &+& 2 \times 10^1 &+& 3 \times 10^0 \\ \end{eqnarray} \end{split}\]

소수점이 있는 경우에는 소수점 아래의 숫자가 \(10^{-1}, 10^{-2}, 10^{-3}, \ldots\) 자리를 나타내는 숫자이다.

\[\begin{split} \begin{eqnarray} 1.2 &=& 1 + 0.2 &=& 1 \times 10^0 &+& 2 \times 10^{-1} \\ 1.123 &=& 1 + 0.1 + 0.02 + 0.003 &=& 1 \times 10^0 &+& 1 \times 10^{-1} &+& 2 \times 10^{-2} + 3 \times 10^{-3} \\ \end{eqnarray} \end{split}\]

연습 문제 2.2.3

다음 십진법 숫자를 10의 제곱의 합으로 풀어서 나타내라.

  1. 1234

  2. 1010

  3. 3.14

  4. 0.023

이진법에서는 0, 1의 2개 숫자만 사용하고 2 이상의 수는 \(2, 4, 8, 16, 32, \ldots\) 자리를 나타내는 숫자를 나열하여 표현한다.

\[\begin{split} \begin{eqnarray} 1 &=& & & & & & & 1 \times 2^0 &=& 1_{(2)} \\ 2 &=& & & & & 2 \times 2^1 &+& 0 \times 2^0 &=& 10_{(2)} \\ 3 &=& & & & & 1 \times 2^1 &+& 1 \times 2^0 &=& 11_{(2)} \\ 4 &=& & & 1 \times 2^2 &+& 0 \times 2^1 &+& 0 \times 2^0 &=& 100_{(2)} \\ 5 &=& & & 1 \times 2^2 &+& 0 \times 2^1 &+& 1 \times 2^0 &=& 101_{(2)} \\ 15 &=& 1 \times 2^3 &+& 1 \times 2^2 &+& 1 \times 2^1 &+& 1 \times 2^0 &=& 1111_{(2)} \\ \end{eqnarray} \end{split}\]

파이썬의 bin 명령을 쓰면 정수인 십진수를 이진수로 변환할 수 있다. 이진수는 숫자 앞에 0b라는 접두사가 붙는다.

bin(3)
'0b11'
bin(15)
'0b1111'

소수점이 있는 경우에도 다음처럼 풀어서 나타낼 수 있다.

\[\begin{split} \begin{eqnarray} 0.5 &=& 1 \times 2^{-1} & & & & &=& 0.1_{(2)} \\ 0.25 &=& 0 \times 2^{-1} &+& 1 \times 2^{-2} & & &=& 0.01_{(2)} \\ 0.125 &=& 0 \times 2^{-1} &+& 0 \times 2^{-2} &+& 1 \times 2^{-3} &=& 0.001_{(2)} \\ 0.75 &=& 1 \times 2^{-1} &+& 1 \times 2^{-2} & & &=& 0.11_{(2)} \\ 0.375 &=& 0 \times 2^{-1} &+& 1 \times 2^{-2} &+& 1 \times 2^{-3} &=& 0.011_{(2)} \\ 0.875 &=& 1 \times 2^{-1} &+& 1 \times 2^{-2} &+& 1 \times 2^{-3} &=& 0.111_{(2)} \\ \end{eqnarray} \end{split}\]

연습 문제 2.2.4

다음 이진법 숫자를 2의 제곱의 합으로 풀어서 나타내라.

  1. 13

  2. 129

  3. 0.8

  4. 1.25

부동소수점 오차

1보다 작은 수의 경우에는 십진법으로 간단히 표현되는 수도 이진법에서는 무한개의 유효숫자를 가질 수 있다. 예를 들어 \(0.1\)이라는 숫자는 십진수로는 간단히 표현되지만 이진수로 나타내면 다음과 같이 \(0011_{(2)}\)이 무한히 반복되는 실수가 된다.

\[ 0.1 = 0.00011001100110011001100110011001100110011001100110011001100110011\cdots_{(2)} \]

그런데 컴퓨터에서는 하나의 숫자를 나타내기 위한 메모리 크기가 제한되어 있어서 특정 소수점 이하는 생략하고 가장 비슷한 숫자로 표현할 수 밖에 없다. \(0.1\)은 실제로는 가장 비슷한 다음과 같은 숫자로 저장된다.

\[ 0.1 \approx 0.1000000000000000055511151231257827021181583404541015625 \]

그런데 파이썬 콘솔이나 주피터 노트북에서 0.1을 입력하면 다음과 같이 그냥 0.1로 나타난다.

0.1
0.1

그 이유는 파이썬 콘솔이나 주피터 노트북과 같은 REPL 인터페이스에서 값이 출력될 때는 편의상 일정 소수점 이하를 생략하고 보여주기 때문이다. 만약 소수점 이하 55자리까지 보고 싶으면 %precision 매직(magic) 명령어를 사용한다.

# 소숫점 55자리까지 표현
%precision 55   
'%.55f'

이 상태에서 다시 0.1이라고 입력하면 55자리까지의 유효숫자를 보여준다.

0.1
0.1000000000000000055511151231257827021181583404541015625

다시 원래대로 돌아가려면 다음과 같이 입력한다.

%precision %r
'%r'
0.1
0.1

이처럼 컴퓨터에서 실수를 계산할 때는 항상 미세한 오차를 가질 수 있으므로 실수의 계산을 할 때는 주의해야 한다. 예를 들어 \(0.1+0.2=0.3\) 이지만 파이썬에서 비교하면 다음처럼 양변이 다르다는 결과를 보인다.

0.1 + 0.2 == 0.3
False

실제로 계산 결과를 보면 그 이유를 알 수 있다.

0.1 + 0.2
0.30000000000000004
%precision 55
'%.55f'
0.3
0.2999999999999999888977697537484345957636833190917968750
%precision %r
'%r'

따라서 실수를 비교할 때는 다음과 같이 round 명령을 사용하여 유효숫자를 지정한 반올림을 한 후에 비교해야 한다. round 명령은 두 번째 인수로 반올림할 소수점 이하의 유효숫자의 개수를 받는다. 다음 명령은 소수점 5자리까지 비교한다.

round(0.1 + 0.2, 5) == round(0.3, 5)
True

또는

round((0.1 + 0.2) - 0.3, 5) == 0.0
True

자료형 변환

실수를 정수로 변환하거나 정수를 실수로 변환하려면 int 명령과 float 명령을 사용한다.

int(1.0)  # 실수를 정수로 변환
1
float(1)  # 정수를 실수로 변환
1.0

만약 정수형으로 변환하려는 숫자가 정확히 정수로 표현될 수 없으면 소숫점 이하의 숫자를 버린다.

int(3.14)
3
int(3.9)
3
int(-3.9)
-3

NaNInf

IEEE 754 표준에 따른 부동소수점 자료형은 특별한 두 가지 값을 표현할 수 있다. 하나가 NaN(Not a Number)이고 또 하나는 Inf(Infinity)이다. NaN는 “숫자가 아닌 것”, Inf는 “무한대”를 뜻한다. 파이썬에서는 다음과 같은 명령으로 표현한다.

float("NaN")
nan
float("Inf")
inf
float("-Inf")
-inf