다운로드
작성자: admin 작성일시: 2017-05-11 15:24:47 조회수: 4723 다운로드: 223
카테고리: Python 태그목록:

부동소수점 실수 자료형

정수와 실수 자료형

파이썬에서는 정수(integer)뿐 아니라 소수점을 포함하는 실수(real number)도 연산할 수 있다. 예를 들어 $10 \div 4$ 또는 $3.14 \times 2 $ 는 다음과 같이 계산할 수 있다.

In [1]:
10 / 4
Out:
2.5
In [2]:
3.14 * 2
Out:
6.28

그런데 정수와 실수는 컴퓨터 메모리에 저장되는 방식이 다르다. 이처럼 데이터에 따라 저장 방식 혹은 처리 방식이 달라지면 데이터의 자료형(type)이 다르다고 한다. 파이썬에서 정수는 integer, 줄여서 int라는 정수 자료형으로 처리되고, 실수는 float라는 부동소수점 실수 자료형으로 처리된다. 파이썬에서 데이터의 자료형을 알려면 type 명령을 사용한다.

또한, 파이썬에서는 숫자에 소수점이 붙어 있으면 실수로 처리한다. 정수부가 0인 소수는 0을 생략할 수 있다.

In [3]:
type(10)
Out:
int
In [4]:
type(10 / 4)
Out:
float
In [5]:
type(0.1)
Out:
float
In [6]:
.1
Out:
0.1
In [7]:
1.
Out:
1.0

부동소수점 실수

컴퓨터에서는 실수를 부동소수점(floating-point) 방식으로 표현하므로 실수를 부동소수점 자료형 숫자(floating-point type number), 줄여서 부동소수점 실수라고도 한다. 부동소수점 방식에서는 숫자를 유효숫자와 소수점 위치를 나타내는 지수의 곱으로 표현한다. 예를 들어 십진수 부동소수점 방식에서 $123.456$이란 숫자는 $123456 \times 10^{-3}$ 이므로 $123456$이라는 유효숫자와 $-3$이라는 지수로 나타낼 수 있다.

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

유효숫자e지수 = 유효숫자 x 10^지수

In [8]:
123e3
Out:
123000.0
In [9]:
123e-3
Out:
0.123
In [10]:
123.456e-10
Out:
1.23456e-08

이진 부동소수점 실수와 표현 오차

그런데 컴퓨터에서는 십진수 부동소수점 방식이 아닌 이진수 부동소수점 방식을 사용한다. 실수를 이진수 부동소수점 방식으로 변환하는 예를 몇가지 들면 아래와 같다.

$$ 2 = 1 \times 2^1 + 0 \times 2^0 = 10_{(2)} $$
$$ 6 = 1 \times 2^2 + 1 \times 2^1 + 0 \times 2^0 = 110_{(2)} $$
$$ 0.5 = 1 \times 2^{-1} = 0.1_{(2)} = 1_{(2)} \times 2^{-1} $$
$$ 0.25 = 1 \times 2^{-2} = 0.01_{(2)} = 1_{(2)} \times 2^{-2} $$
$$ 0.75 = 1 \times 2^{-1} + 1 \times 2^{-2} = 0.11_{(2)} = 11_{(2)} \times 2^{-2} $$
$$ 0.375 = 1 \times 2^{-2} + 1 \times 2^{-3} = 0.011_{(2)} = 11_{(2)} \times 2^{-3} $$

이진수 부동소수점 방식의 문제점은 십진수로 간단히 표현되는 소수도 이진수에서는 무한개의 유효숫자를 가지는 소수가 될 수 있다는 점이다. 예를 들어 $0.1$이라는 숫자는 십진수로는 간단히 표현되지만 이진수로 나타내면 다음과 같이 $0011_{(2)}$이 무한히 반복되는 소수가 된다.

$$ 0.1 = 0.00011001100110011001100110011001100110011001100110011001100110011\cdots_{(2)} $$

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

$$ 0.1 \approx 0.1000000000000000055511151231257827021181583404541015625 $$

그런데 실제로 0.1을 입력하면 다음과 같이 그냥 0.1로 나타난다.

In [11]:
0.1
Out:
0.1

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

In [12]:
%precision 55
Out:
'%.55f'
In [13]:
0.1
Out:
0.1000000000000000055511151231257827021181583404541015625

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

In [14]:
%precision % r
Out:
'%r'
In [15]:
0.1
Out:
0.1

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

In [16]:
0.1 + 0.2 == 0.3
Out:
False

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

In [17]:
0.1 + 0.2
Out:
0.30000000000000004
In [18]:
%precision 55
Out:
'%.55f'
In [19]:
0.3
Out:
0.2999999999999999888977697537484345957636833190917968750
In [20]:
%precision % r
Out:
'%r'

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

In [21]:
round(0.1 + 0.2, 5) == round(0.3, 5)
Out:
True

또는

In [22]:
round((0.1 + 0.2) - 0.3, 5) == 0.0
Out:
True

형 변환

int 명령과 float 명령은 각각 실수를 정수로 변환(conversion)하거나 정수를 실수로 변환할 때 사용한다.

In [23]:
int(1.0)
Out:
1
In [24]:
float(1)
Out:
1.0

만약 정수형으로 변환하려는 숫자가 정확히 정수로 표현될 수 없으면 내림(floor)을 한다.

In [25]:
int(3.14)
Out:
3
In [26]:
int(3.9)
Out:
3

NaN과 Inf

부동소수점 자료형은 특별한 두 가지 숫자를 표현할 수 있다. 하나가 NaN(Not a Number)이고 또 하나는 Inf(Infinity)이다. 이는 각각 “숫자가 아닌 수”와 “무한대”를 뜻한다. 파이썬에서 이 숫자들은 다음과 같은 명령으로 쓸 수 있다. 이 값이 나오는 예에 관하여는 NumPy 패키지를 소개할 때 다시 설명한다.

In [27]:
float("NaN")
Out:
nan
In [28]:
float("Inf")
Out:
inf

질문/덧글

round 명령 관련 질문입니다 tric*** 2018년 9월 27일 5:51 오후

안녕하세요. round 명령을 사용하여 유효숫자를 지정한 반올림을 한 후에 비교해야 한다.

round 명령은 두 번째 인수로 반올림할 소수점 이하의 유효숫자의 개수를 받는다.

본문에서는 소수점 5자리까지 비교를 했는데

그냥 round(0.1 + 0.2) == round(0.3) 을 입력해도 true라는 결과가 나오네요. 자릿수를 아무것도 입력하지 않으면 몇번째 자리로 설정이 되는건가요?

답변: round 명령 관련 질문입니다 관리자 2018년 9월 27일 6:41 오후

정수로 라운딩합니다.

```
In [1]: round(0.1 + 0.2)
Out[1]: 0

In [2]: round(0.3)
Out[2]: 0
```