끝나지 않는 프로그래밍 일기

1. 자료형(Data Type)은 무엇인가?

이번 편에서는 자료형(Data Type)에 대해서 알아보도록 하겠습니다. 자료형은 말 그대로, 데이터의 형식을 말합니다. 파이썬에서는 수치 자료형부터 시작해서 문자 자료형, 튜플, 리스트, 사전 등 여러가지의 자료형이 존재하며, 자료형을 보고서 데이터가 어떠한 데이터의 형식인지 알 수 있습니다. 파이썬에 내장되어 있는 함수인 type이란 함수를 통해서 객체의 타입을 살펴보도록 하겠습니다. 이 type이란 함수는 객체의 타입을 보여주며, 아래와 같이 사용합니다.

>>> type(33)
<class 'int'>
>>> type(3.14)
<class 'float'>
>>> type(['1', '2', '3'])
<class 'list'>
>>> type(33331491491492)
<class 'int'>

위를 보시면 객체 33의 타입은 int로, 이는 정수(integer)를 의미합니다. 객체 3.14는 float이므로 실수(float)를 의미합니다. 그 아래에 있는 대괄호로 감싸진 녀석은 리스트라는 녀석인데, 이 리스트란 개념은 좀 더 뒤에가서 설명합니다. 아직은 이것이 무엇인지 아실 필요는 없습니다. 수치 자료형, 문자 자료형, 리스트, 튜플, 사전 이런 식으로 차례대로 설명을 할 계획이며, 우선은 숫자를 나타내는 수치 자료형(Numeric Data Type)에 대해서 알아보도록 합시다.


2. 정수(Integer)

위에서 말한대로 파이썬에서 등장하는 int라는 녀석은 정수(Integer)의 약자입니다. 아래에 변수에 대입이 되는 객체들은 모두 정수형 객체이며, 그 중에서도 가장 많이 쓰이는 10진수의 예입니다.

>>> A = 5
>>> B = 10
>>> print(A, B)
5 10

정수를 10진수가 아닌 2진수, 8진수, 16진수로 인식하게 하고 싶으면 정수 앞에 각각 '0b', '0o', '0x'를 붙이시면 됩니다. 아래와 같이 말입니다.

>>> print(0b10, 0o10, 0x10)
2 8 16

위에서 b는 2진수(binary), o는 8진수(octal), x는 16진수(hexadecimal)라는 의미입니다. 반대로 10진수를 각각 2진수, 8진수, 16진수의 형태로 변환하려면 bin, oct, hex 함수를 사용하시면 됩니다.

>>> bin(202020)
'0b110001010100100100'
>>> oct(20114)
'0o47222'
>>> hex(401000)
'0x61e68'

여기서 주의하셔야 할 부분은, 위에 보시면 출력되는 결과가 정수가 아니라 문자열이라는 것입니다. 즉, 'hex(40) - 20'과 같은 연산에서 hex(40)이 내보내는 결과는 문자열(string), 20은 정수(integer)이니 타입이 맞지 않아 서로 연산을 하지 못합니다. 문자열에 대해서는 다음 편인 문자열 강좌에서 다루니 궁금하신 분은 미리 살펴보고 오셔도 괜찮습니다. 


3. 실수(Float)

파이썬에서 등장하는 float라는 녀석은 부동 소수점(Floating point)의 약자이며, 부동 소수점이란 정수처럼 소숫점이 고정되어 있는게 아니라 부동이란 의미 그대로 고정되어 있지 않고 움직인다는 말입니다. 이 방식은 컴퓨터에서 실수를 표현하는 방식이며, 소숫점의 위치를 나타내는 수를 따로 기록합니다. 앞으로 float라는 단어가 나오면, 이는 부동 소수점이 아니라 실수라는 의미로 설명하도록 하겠습니다. 아래의 예제에서 변수에 대입되는 객체는 모두 실수 형태의 객체라고 말할 수 있습니다.

>>> A = 3.14
>>> B = 5.1402020319
>>> print(A, B)
3.14 5.1402020319

위처럼 실수를 표현하는 방식도 있겠지만, 다른 방식으로는 지수 표기법이라는 것으로 아래와 같이 실수를 표현하는 방식이 존재합니다.

>>> 0.23193202032E8
23193202.032
>>> 1412232.22E-10
0.000141223222

위 코드에서 E는 지수(Exponent)라는 의미이며, 대문자가 아니더라도 소문자 역시 똑같은 의미로 사용됩니다. 위의 예제에서 0.23193202032E8는 0.23193202032 * 10^8이라고 보시면 됩니다. 여기서 10^n은 10의 n승이라는 것입니다. 즉, 0.23193202032 곱하기 10의 8승은 23193202.032라는 값을 지니고, 1412232.22E-10에서는 10^-10이니 이것은 1412232.22 곱하기 10의 마이너스 10승을 의미하며, 0.000141223222라는 값을 가집니다. 한가지 주의하실 부분이 있는데, 한번 아래의 예제를 살펴보도록 합시다.

>>> 5.4 + 1.2
6.6000000000000005
>>> 1.4 - 1.1
0.2999999999999998

우리가 예상하기에는 위의 예제의 결과가 각각 6.6, 0.3으로 나와야 할텐데 이상한 결과가 나오고 있는 것을 확인하실 수 있습니다. 이는 진법 변환에 따른 오차에 의한 것으로 10진수를 2진수로 변환시킬때 10진수의 유한 소수가 2진수에선 무한 소수가 되는 경우가 있다고 합니다. 진법 변환을 간단히 소개하자면, 10진수 0.125를 2진수로 고치면 

0.125 * 2 = 0.25 (0)
0.25 * 2 = 0.5 (0)
0.5 * 2 = 1.0 (1)
0.0 (계산 마침)

위와 같이 계산되어 최종적으로 2진수 0.001이 되는 것입니다. 참고로 여기서 괄호 안의 숫자는 정수 부분만을 취한 것입니다. 이와 같은 방법으로 10진수 0.1를 2진수로 변환한다고 하면 아래와 같을 것입니다.

0.1 * 2 = 0.2 (0)
0.2 * 2 = 0.4 (0)
0.4 * 2 = 0.8 (0)
0.8 * 2 = 1.6 (1)
...

소수부가 0이 나올때까지 2를 곱하게 되는데, 여기서 뒷자리를 자세히 살펴보시면 2,4,8,6의 반복으로 계속 끝이 없는 무한 소수가 되어 나오는 것을 확인하실 수 있습니다. 이는 사실 파이썬 자체만의 문제가 아니라 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준인 IEEE 754를 따르는 프로그래밍 언어들이 이러한 문제를 가지고 있습니다. 결과가 이상하게 나오더라도 진법 변환에서 생기는 오차라고 생각하시고, 만약에 더욱더 정밀한 계산을 해야 한다면 파이썬의 decimal 모듈을 사용할 수 있습니다.


4. 복소수(Complex)

파이썬에서는 정수와 실수뿐만 아니라 좀더 넓은 개념인 복소수까지도 내부적으로 지원합니다. 여기서 허수 단위는 j 또는 J입니다. 복소수는 a + bj 꼴로 나타낼 수 있으며, 실수 a를 그 복소수의 실수부, 실수 b를 복소수의 허수부라고 부릅니다. 복소수에 관해서는 이미 알고있다고 가정하며, 간단하게 설명하도록 하겠습니다. 우선은 아래의 예제를 보도록 합시다. 

>>> x = 7 - 3j
>>> type(x)
<class 'complex'>

위 예제에서 쓰인 바와 같이 ‘7 – 3j’이 복소수이며, 이를 변수 x에 할당했습니다. 그리고 파이썬 내장 함수인 type()를 통해서 변수 x가 복소수를 담고 있음을 확인할 수 있습니다. 이번에는 복소수의 실수부와 허수부만 따로 가져와 보도록 하겠습니다. 

>>> x.imag 
-3.0 
>>> x.real 
7.0 
>>> x.conjugate() 
(7+3j) 

위 예제에서 imag는 복소수의 허수 부분을 돌려주고, real은 복소수의 실수 부분을 되돌려줍니다. 그리고 conjugate 함수는 복소수의 켤레 복소수(conjugate complex number)를 되돌려줍니다. 

>>> y = complex(2.5, 4)     # y = 2.5 + 4j 
>>> x + y 
(9.5+1j) 
>>> x - y 
(4.5-7j) 
>>> x / y 
(0.24719101123595505-1.595505617977528j) 
>>> x * y 
(29.5+20.5j) 

위 예제에서 complex 함수로 실수부와 허수부를 넘겨줌으로써 복소수를 만들 수도 있습니다. 그렇게 만들어진 복소수와 아까 할당한 변수 x와 사칙연산을 할 수도 있습니다. 예제를 하나 더 보도록 합시다. 

>>> complex(1.1, 3.4) + 2j * 7.6j 
(-14.1+3.4j) 
>>> complex(3) 
(3+0j) 
>>> complex("7-2j") 
(7-2j) 

complex 함수로 실수부만 넘길 수 있고, 복소수의 형태를 갖춘 문자열을 넘겨도 복소수를 만들 수 있습니다. 

>>> z = 3 + 4j 
>>> abs(z) 
5.0 
절댓값을 구하는 abs() 함수를 통해서 복소수 3+4j의 절댓값을 얻을 수 있습니다. 복소수 3+4j의 절댓값은 sqrt(3^2 + 4^2)입니다. 

  지나가는 이야기. 왜 파이썬은 i를 허수 단위로 쓰지 않는가? 

Q1. 정수 문제 (☆☆☆☆)

정수 617를 내장 함수(bin, oct, hex)를 통해서 출력해보세요.

Q2. 실수 문제 (☆☆☆☆)

실수와 정수끼리 사칙연산을 한 다음에 출력해보세요. (연산자 최소 3개 이상 사용 요구)