처음부터 차근차근 파이썬 자세히보기

Python-기본/Python-데이터 타입 및 자료 구조

Python-2. 숫자 데이터 타입 다루기

윤빵빵영 2020. 12. 14. 18:20

 


목차

1. 정수(Integer)
2. 2/8/16진법
3. 자료형 변환
    type(x)
    int(x)
    str(x)
4. 실수(Float, 부동소수점)
    float(x)
    부동소수점
    round(n, a)
5. 숫자형 자료를 다루기 위한 연산자
    +(덧셈), -(뺄셈), *(곱셈), **(제곱), /(나눗셈)
    %(나머지 반환), //(몫 반환)
    +=, -=, *=, /=, **=, %=, //=


이번 글부터는 파이썬에 내장되어 있는 데이터 타입(data type, 자료형)에 대해서 알아보겠습니다. 파이썬에 기본적으로 제공하는 데이터 타입 및 데이터 구조(data structure, 자료 구조)에는 여러 가지가 있으며, 여러 자료를 토대로 다음과 같이 나누어 정리해보았습니다.

이외에도 숫자형에는 복소수(특정 모듈을 import할 필요가 있습니다), 시퀀스형에는 바이트, 바이트 배열, 컬렉션에는 파이썬 컬렉션 데이터 타입인 기본 딕셔너리/정렬된 딕셔너리/카운터 딕셔너리 등이 있지만 가장 기본적인 자료형부터 정리해나가도록 해봅시다.

지난 글에서 만들어두었던 파이참 프로젝트에서 test.py를 만든 뒤 숫자형 데이터를 다루는 방법을 배워봅시다.

 

1. 정수(Integer)

파이썬은 기본적으로 정수(integer)와 부동 소수점(floating point)에 대한 내장 지원(built-in support)을 제공합니다. 즉, 정수와 부동 소수점은 파이썬에서 제공하는 자료형으로 별다른 설정 없이도 기본적인 연산과 조작이 가능하다는 것입니다. 

파이썬에서 정수는 int로 나타내며 불변형(immutable)입니다. 자료형을 토대로 소스 코드를 본격적으로 다루려면 객체(object), 불변형/가변형(immutable/mutable), 변수 공간, 변수 등 알아야 할 개념이 많은데, 이런 어려운 개념들을 지금 당장 익힐 필요는 없습니다. 우선은 코드를 따라 작성해서 실행해보고 부딪혀 보면서 가볍게 시작한 뒤 나중에 다시 정리해보도록 합시다.

기본적인 숫자들 간의 연산은 아래에 있는 연산자를 이용하여 할 수 있습니다.

연산자 설명 예시 결과
+ 덧셈 5 + 8 13
- 뺄셈 90 - 10 80
* 곱셈 4 * 7 28
/ 나눗셈 7 / 2 3.5
// 나눗셈의 몫(가우스 연산) 7 // 2 3
% 나눗셈의 나머지 7 % 3 1
** 제곱 3 ** 4 81

 

다음은 정수 3을 출력하는 소스 코드입니다.

x = 3
print(x)

실행하기 위해서는 ctrl + shift + F10을 누릅니다. 실행 결과는 다음과 같습니다.

결과)

3


파이썬에서 일련의 숫자들은 모두 정수로 인식됩니다. 다음과 같이 여러 정수를 출력해봅시다.

x = 127
y = -395498
z = 34
print(x)
print(y)
print(z)

결과)

127
-395498
34


숫자 0을 그대로 사용할 수도 있지만, 다른 숫자 앞에 사용할 수는 없습니다.

x = 0
print(x)

결과)

0

 

x = 05
print(x)

결과)

x = 05
     ^
SyntaxError: invalid token


위와 같이 코드가 실행되지 않고, 코드 내 오류인 부분을 알려주면서 어떠한 프로그램 에러(error)가 발생했는지를 알려주는 것을 Python exception(예외)라고 합니다. 위의 경우 05가 "invalid token"임을 경고하고 있습니다. 앞으로 다양한 코드를 다루면서 발생할 에러들을 다룰 것이니 이번엔 넘어가도록 하겠습니다.

기본적으로 일련의 숫자들은 양의 정수임을 의미합니다. 숫자 앞에 +기호를 붙이더라도, 숫자는 그대로 남습니다.

x = +238
print(x)

결과)

238


음의 정수를 이용하기 위해서는 - 기호를 숫자 앞에 붙여야 합니다.

x = -238
print(x)

결과)

-238


앞서 언급했듯 파이썬에서 정수는 내장 자료형이므로 정수를 가지고 할 수 있는 일들이 있습니다. 가장 기본적인 연산 역시 가능합니다.

x = 5 + 9
print(x)
y = 100 - 7
print(y)

결과)

14
93


물론 많은 수의 덧셈/뺄셈을 하는 것도 가능합니다.

x = 5 + 9 + 3
print(x)
print(4 + 3 - 2 - 1 + 6)

결과)

17
10


이때 숫자와 연산자(+, -) 사이에 공백을 반드시 넣을 필요는 없습니다. 공백의 크기도 아무런 문제가 되지 않습니다. 그저 코드가 읽기 좋거나 보기 좋게 하기 위해 (저의 경우는) 공백을 하나씩 넣습니다.

x = 5+         3
print(x)

결과)

17


곱셈도 직관적으로 사용하시면 됩니다.

x = 6 * 7
y = 6 * 7 * 2 * 3
print(x)
print(y)

결과)

42
252


나눗셈과 관련된 연산으로는 세 가지가 있습니다. 일반적인 나눗셈은 '/' 기호를, 나눗셈의 몫을 구할 때는 '//'를, 나머지를 구할때는 '%'를 이용합니다.

x = 9 / 5
y = 9 // 5
z = 9 % 5
print(x)
print(y)
print(z)

결과)

1.8
1
4


0으로 나누는 것은 파이썬 예외를 불러 일으킵니다. 수학에서도 0으로 나누는 것은 정의하지 않습니다.

x = 5 / 0
print(x)

결과)

x = 5 / 0
ZeroDivisionError: division by zero

 

x = 5 // 0
print(x)

결과)

x = 5 // 0 
ZeroDivisionError: integer division or modulo by zero

 

x = 5 % 0
print(x)

결과)

x = 5 % 0 
ZeroDivisionError: integer division or modulo by zero


변수에 숫자를 할당할 때 일어나는 과정을 살펴봅시다.

x = 95
x - 3
print(x)

결과)

95


코드의 흐름을 관찰해봅시다. x = 95를 선언함으로서 95라는 정수형 값을 변수명 x에 할당했습니다. 이후에 x - 3을 연산합니다. 이후에 다시 x를 출력했지만 결과는 95가 되었습니다. 변수에 값을 할당할 때는 반드시 '=' 기호를 사용해야합니다. 즉, x - 3 연산을 진행했지만, 이는 연산의 결과를 x라는 변수에 할당했다는 뜻이 아니므로 x를 출력하면 처음에 할당된 값이 95가 출력되는 것입니다. x라는 변수에 원래 값에서 3을 뺀 결과를 다시 할당하기 위해서는 코드를 아래와 같이 작성해야 합니다.

x = 95
x = x - 3
print(x)

결과)

92


x = x - 3 코드는 얼핏 보면 수학적 관점에서 어색해보일 수 있습니다. 하지만 파이썬에서 '='는 우변을 계산한 후 좌변에 할당한다는 의미를 갖기 때문에 전혀 어색하지 않습니다. 위와 같이 값이 할당된 변수에서 연산을 한 뒤 같은 변수명에 재할당할 때 다음과 같이 줄여쓸 수 있습니다.

x = 95
x = x - 3
print(x)
x -= 3
print(x)

결과)

92
89


다른 연산 기호도 마찬가지입니다.

x = 92
x += 8
print(x)
x *= 2
print(x)
x /= 3
print(x)
y = 13
y //= 4
print(y)

결과)

100
200
66.66666666666667
3

 

2. 2/8/16진법

정수는 기본적으로 다른 진법을 사용한다는 특정한 표시가 없다면 10을 기저로하는 10진법의 수를 말합니다. 아마 저를 포함한 많은 분들이 살면서 다른 수를 기저로하는 진법을 사용할 일이 없을지도 모르지만, 파이썬은 내장형 데이터 한 켠에 다른 진법의 수를 사용할 수 있는 기능을 제공하고 있습니다.

파이썬에서 10진법이 아닌 다른 진법의 숫자를 다음과 같은 방법으로 표현할 수 있습니다.

- 0b 또는 0B (2진법, binary의 b)
- 0o 또는 0O (8진법, octal의 o)
- 0x 또는 0X (16진법, hex의 x)

파이썬 인터프리터는 위를 이용하여 표현된 다른 진법의 숫자를 10진법의 숫자로 변환합니다. 

x = 0b101
print(x)

결과)

5


0b101은 2진법으로 표현된 수 101을 말합니다. 이는 10진법으로 변환하면 1x(2^2)+0x(2^1)+1x(2^0)=5가 되며 파이썬은 이를 자동적으로 5로 변환하여 사용합니다.

x = 0o101
print(x)

결과)

65


마찬가지로 8진법으로 표현된 수 101을 10진법으로 변환하면 1x(8^2)+0x(8^1)+1x(8^0)=65입니다.

x = 0x101
print(x)

결과)

257


16진법으로 표현된 수 101을 10진법으로 변환하면 1x(16^2)+0x(16^1)+1x(16^0)=257입니다.

다음으로 진법과 관련된 몇 가지 함수를 보겠습니다. bin(i)는 정수 i의 2진수 '문자열'을 반환합니다.

x = bin(999)
print(x, type(x))

결과)

0b1111100111 <class 'str'>


결과가 문자열 타입임에 유의해야 합니다. type(x)는 x의 자료형이 무엇인지를 출력합니다.

oct(i)는 정수 i의 8진수 문자열을 반환합니다. hex(i)는 정수 i의 16진수 문자열을 반환합니다.

x = oct(999)
y = hex(999)
print(x, type(x))
print(y, type(y))

결과)

0o1747 <class 'str'> 
0x3e7 <class 'str'>

 

3. 자료형 변환

type(x)

변수에 할당된 데이터나 입력된 값의 타입(자료형)을 알고 싶다면 type( )을 활용하면 됩니다.

x = -238
type(x)

결과)

<class 'int'>


<class 'int'>는 해당 변수가 정수 타입의 데이터임을 말합니다. 뒤에서 다루겠지만 문자열(string, str) 타입의 데이터는 따옴표(' ' 또는 " ")를 이용하여 입력합니다.

print(type("abc"))

결과)

<class 'str'>

<class 'str'>는 해당 입력값이 문자열 타입의 데이터임을 말합니다.

 

int(x)

목적에 맞는 소스 코드를 짜다 보면 함수의 입력값과 출력값의 데이터 타입이 다른 경우가 많습니다. 예를 들어 어떤 함수의 결과물로 얻은 값이 문자열 타입인데 이 값을 받아서 다음 함수에 대입할 때는 정수형으로 전환하여 바꿔야 하는 경우가 있습니다. 이 경우 int( )를 이용하여 해당 값을 정수형으로 변환해줄 수 있습니다.

x = "45"
y = int(x)
print(y)
print(type(y))

결과)

45
<class 'int'>

 

x = "-23"
y = int(x)
print(y)
print(type(y))

결과)

-23
<class 'int'>


숫자로 구성된 문자열 타입의 데이터가 아닌 문자로 구성된 값을 int()에 대입하면 오류 메시지를 출력합니다.

x = int("Hello World!")

결과)

ValueError: invalid literal for int() with base 10: 'Hello World!'


또한 빈 문자열 값도 int()에 대입하면 오류 메시지를 출력합니다.

x = int("")

결과)

ValueError: invalid literal for int() with base 10: ''


파이썬에는 불(bool, boolean)이라 불리는 가장 단순한 자료형이 있습니다. 오직 TrueFalse만을 값으로 가지며 동시에 정수형으로 전환될 수 있습니다.

print(int(True))
print(int(False))

결과)

1
0


뒤에서 다루겠지만 부동소수점 수를 정수로 변환하면 소수점 이하의 수를 버리게 됩니다.

x = int(98.6)
y = int(1.0e4)
print(x)
print(y)

결과)

98
10000


1.0e4는 부동소수점 수 10000.0을 말합니다. 

int( )는 부동소수점 수 및 정수로 표현된 문자열을 정수로 변환할 수는 있지만, 소수점이나 지수가 포함된 문자열을 정수로 변환할 수는 없습니다.

x = int('98.6')
print(x)

결과)

ValueError: invalid literal for int() with base 10: '98.6'

 

x = int('1.0e4')
print(x)

결과)

ValueError: invalid literal for int() with base 10: '1.0e4'


순서가 좀 엇갈렸지만 자료형 변환을 위해서 정수형 이외에 문자열, 불, 부동소수점 등의 자료형을 맛만 봤습니다. 숫자 사이에는 연산이 가능하므로 정수형 자료와 부동소수점형 자료 사이의 연산은 기본적으로 가능하며, 연산 결과는 부동소수점 수가 됩니다.

x = 4 + 7.0
print(x)
print(type(x))

결과)

11.0
<class 'float'>


또한 불 자료형과도 연산이 가능합니다. 이때 True는 1 취급을, False는 0 취급을 합니다.

x = True + 2
y = False + 5.0
print(x)
print(y)

결과)

3
5.0

 

str(x)

반대의 경우도 생각해볼 수 있습니다. 계산 결과 얻게 된 정수형 데이터를 다음에 문자열로서 활용하고 싶을 때가 있습니다. 이때는 str( )을 이용합니다.

x = 1
y = x + 4
z = str(y)
print(z)
print(type(z))

결과)

5 
<class 'str'>

 

4. 실수(Float, 부동소수점)

파이썬은 실수형 데이터 타입도 내장 데이터 타입으로 기본 제공합니다. 파이썬에서 부동소수점은 float로 나타내며 불변형입니다. 

실수형 데이터의 타입을 확인하면 다음과 같습니다.

x = 3.141592
print(type(x))

결과)

<class 'float'>


<class 'float'>는 해당 입력값이 실수형 타입의 데이터임을 말합니다. 다음과 같이 유효 숫자와 10의 지수형으로 데이터를 출력할 수 있으며 이때 데이터 타입은 실수형입니다.

x = -1.49E02
y = 3.14e-05
print(x, type(x))
print(y, type(y))

결과)

-149.0 <class 'float'>
3.14e-05 <class 'float'>

 

float(x)

정수형 또는 정수를 표현한 문자열, 부동소수점 수를 표현한 문자열은 모두 실수형으로 전환할 때 float( )을 이용합니다.

x1, x2 = 123, "-12.59"
y1 = float(x1)
y2 = float(x2)
print(y1, type(y1))
print(y2, type(y2))

결과)

123.0 <class 'float'>
-12.59 <class 'float'>


불형 자료도 float( )을 이용하여 부동소수점 수로 변환할 수 있습니다.

x = float(True)
y = float(False)
print(x)
print(y)

결과)

1.0
0.0


int( )와 마찬가지로 숫자로 구성된 문자열 타입의 데이터가 아닌 문자로 구성된 값을  float()에 대입하면 오류 메시지를 출력합니다. 또한 빈 문자열 값도 float( )에 대입하면 오류 메시지를 출력합니다.

x = "윤영"
y = float(x)

결과)

ValueError: could not convert string to float: '윤영'

 

 

아래의 이야기는 관심있는 분들이 읽어보시면 좋습니다. 내용이 어려우신 분은 다음 파란색 줄로 넘어가시면 됩니다.

 

부동소수점

컴퓨터는 2진법으로 데이터를 다룹니다. 정수는 2진법으로 나타내기 쉽지만 실수는 2진법으로 다루는게 어렵습니다. IEEE 754는 전기 전자 기술자 협회(IEEE, Institute of Electrical and Electronics Engineers)에서 개발한, 부동소수점을 표현하는 가장 널리 쓰이는 표준입니다.

32비트 부동소수점을 나타낼 때 1비트는 부호(0: 양수, 1: 음수), 23비트는 유효 숫자 자릿수(가수, mantissa), 8비트는 지수(exponent)를 나타내는데 사용됩니다.

10진법으로 나타낸 -118.625를 32비트 단정도로 표현하는 과정은 다음과 같습니다. 우선 부호가 음수이므로 부호에 해당되는 비트는 1입니다. 다음으로 숫자의 절댓값을 이진수로 변환합니다.

즉, 118.625를 2진법으로 표현하면 1110110.101(2)입니다. 이를 다음과 같이 정규화할 수 있습니다.

118.625를 1.18625E02로 표현할 수 있는 것처럼 2진법으로 표현된 수에서 소수점을 왼쪽으로 이동시키며 이동시킨 수만큼 2의 제곱수(지수)를 곱하면 됩니다. 소수점 이하의 숫자를 가수부(23비트)에 넣습니다. 부족한 자릿수는 0으로 채웁니다.

지수가 6이므로 바이어스(bias)를 더합니다. 바이어스는 부호가 있는 큰 값과 작은 값을 모두 나타낼 수 있또록 하는 작업입니다. 여기서는 지수 6에 127(2^7 - 1 = 01111111(2))을 더한 뒤 2진법으로 나타냅니다.

이상의 결과를 종합하여 -118.625를 32비트 단정도로 표현한 결과는 다음과 같습니다.

배정도 방식에서는 64비트 부동소수점을 나타낼 때 1비트는 부호, 52비트는 가수, 11비트는 지수로 나타냅니다. 바이어스 작업에서는 1023(2^10 - 1)을 더하여 2진법으로 수정합니다.

파이썬 자료구조와 알고리즘, 미아 스타인 지음, 최길우 옮김, 한빛미디어
 

 

부동소수점은 이진수 분수(binary fraction)으로 표현되기 때문에 단순히 비교하거나 빼면 안됩니다. 2진법으로 표현하기 어려운 숫자가 있기 때문입니다. 예를 들어 10진법으로 표현된 0.1을 2진법으로 고쳐봅시다.

0.1 = 0.00110011001100...(2)와 같이 10진법일 때는 유한 소수였던 숫자가 2진법으로 나타내면 무한 소수가 됩니다. 컴퓨터는 입력된 값을 2진법으로 전환하여 처리한 뒤 다시 10진법으로 전환하여 출력해주므로 이 과정에서 문제가 발생하게 됩니다. 다음의 예를 봅시다.

x = 1.2
y = 0.1 
print(x - y)

결과)

1.0999999999999999


이와 같이 1.2 - 0.1 = 1.1이라는 것을 우리는 알고 있지만 출력 결과는 1.0999999999999999가 됩니다. 때문에 실수형 데이터를 다루는 데는 주의할 필요가 있습니다.

숫자형 데이터가 서로 동등한지를 확인하기 위해서는 == 부호를 사용합니다. 두 값이 완전히 동등하다면 True, 동등하지 않다면 False를 출력합니다.  

print(0.2 * 3)
print(0.2 * 3 == 0.6)
print(1.2 - 0.2)
print(1.2 - 0.2 == 1.0)
print(1.2 - 0.1)
print(1.2 - 0.1 == 1.1)
print(0.1 * 0.1)
print(0.1 * 0.1 == 0.01)

결과)

0.6000000000000001
False
1.0
True
1.0999999999999999
False
0.010000000000000002
False


위와 같이 10진법 상에서는 문제 없는 연산도 컴퓨터를 거치면 문제가 생길 수 있습니다. 때문에 위와 같은 동등성 테스트(equality test) 및 연산은 사용자가 사전에 정밀도 범위를 정의하여 수행하는 것이 좋습니다. 이때 사용할 수 있는 것이 round( )입니다.

 

round(n, a)

숫자 n을 소수점 이하 a자리까지 나타냅니다. 소수점 이하 (a + 1)자리에서 반올림하며 반올림하는 숫자가 5라면 앞의 자리가 홀수일 때는 올리고 짝수일 때는 내립니다.

print(round(3.141592, 2))
print(round(1.245, 2))
print(round(1.255, 2))

결과)

3.14
1.25
1.25

 

5. 숫자형 자료를 다루기 위한 연산자

마지막으로 정수형, 부동소수점형, 불형 자료의 연산을 위한 연산자를 정리하겠습니다.

+(덧셈), -(뺄셈), *(곱셈), **(제곱), /(나눗셈)

정수는 덧셈, 뺄셈, 곱셈, 제곱 연산에 대해 닫혀있기 때문에 정수에 대한 덧셈, 뺄셈, 곱셈, 제곱 연산의 결과는 정수형입니다. 나눗셈 연산에 대해 닫혀 있는 수의 범위가 실수이므로 나눗셈 연산 또는 실수형 데이터가 연산에 포함되면 실수형 결과를 출력합니다.

x = 3
y = 5
z = x + y
print(z, type(z))
z = x - y
print(z, type(z))
z = x * y
print(z, type(z))
z = x ** y
print(z, type(z))

결과)

8 <class 'int'>
-2 <class 'int'>
15 <class 'int'>
243 <class 'int'>

 

x = 3
y = 5
z = x / y
print(z, type(z))
y = 1.2
z = x + y
print(z, type(z))
z = x - y
print(z, type(z))
z = x * y
print(z, type(z))
z = x ** y
print(z, type(z))

결과)

0.6 <class 'float'>
4.2 <class 'float'>
1.8 <class 'float'>
3.5999999999999996 <class 'float'>
3.7371928188465517 <class 'float'>

 

%(나머지 반환), //(몫 반환)

x = 124
y = 5
a = x // y
b = x % y
print(a, b)
print(a * y + b)

결과)

24 4
124

 

+=, -=, *=, /=, **=, %=, //=

파이썬에서 =는 수학의 equal의 의미가 아니라 변수에 값을 할당(assign)하는 의미입니다. 따라서 다음과 같은 할당도 가능합니다.

x = 100
x = x - 20
print(x)

결과)

80

이때 x = x - 20을 단순하게 표현하여 x -= 20과 같이 표현할 수 있습니다. 위의 모든 연산에 대해 이를 적용할 수 있습니다.

a = 100
a += 20
print(a)
b = 10
b -= 20
print(b)
c = 2
c *= 4
print(c)
d = 3
d **= 22
print(d)
e = 2408
e %= 10
print(e)
f = 1239
f // 5
print(f)

결과)

120
-10
8
31381059609
8
1239