2021년 4월 11일 일요일

프로그래밍 언어에서 데이터 타입은 왜 사용할까?

프로그래밍 언어에서 데이터 타입은 왜 사용할까?


프로그래밍 언어에 대한 관심이 참 높은 요즘입니다. 어린이들에게 코딩 교육을 한다는 사교육 기관도 많고, 또 아이들 학습때문에 혹은 취미생활로 또는 시스템 트레이딩 등 투자활동을 하기 위해 코딩을 익히려는 관심이 점점 증가하는 것 같습니다. 이 블로그에서는 프로그래밍 언어를 익히는데 있어서 필수적인 개념을 쉽게 설명하는 것을 목적으로 합니다. 설명의 구체적인 예는 누구나 쉽게 접근할 수 있고 현대 프로그래밍에 가장 앞선 모습을 보이는 python 3를 기준으로 합니다.

프로그래밍 언어 교재 중 많은 수가 도입부에서 몇 가지 데이터 타입에 대한 설명으로부터 시작합니다. 문자열인 String, 정수형인 Integer, 실수형인 Float, 참과 거짓을 나타내는 Boolean 등에 대해 설명을 나열하지만 잘 와닿지 않는 것 같습니다. 왜 데이터 타입을 사용해야 할까요?

이 글에서 결론부터 우선 말하자면, 프로그래밍 언어로 작성 (코딩)한 내용을 컴퓨터가 이해하고 실행할 수 있도록 해주는 번역 및 실행하는 과정에서 컴파일러나 인터프리터가 해당 값을 어떻게 다루어야 하는지 지시하기 위한 것이기 때문입니다. 몇 가지 사례로 위 결론을 구체화 해보겠습니다.

예를 들어, python 3에서 정수형 (int) 데이터 타입 둘을 * 연산자로 연결하면 python 인터프리터는 이를 곱셈으로 인식합니다.

>>> 14 * 3

42

하지만 문자열 (str) 데이터 타입의 값과 정수형 데이터 타입의 값 둘을 * 연산자로 연결하면 인터프리터는 이를 해당 문자열을 지정된 회수만큼 반복하는 문자로 만들어줄 것으로 인식합니다.

>>> ’ho’ * 3

‘hohoho’

모든 컴퓨터 프로그래밍 언어는 Java, C#과 같이 명시적으로 선언하고 데이터 타입에 따라 값에 대한 연산 혹은 함수를 적용 할 때 다르게 처리하도록 하거나 python이나 Javascript 등과 같이 인터프리터가 알아서 유추할 수 있게 힌트를 주어 눈치껏 처리하도록 하는 방식으로 되어있습니다.

다시 python으로 돌아가서 python은 홑따옴표 혹은 쌍따옴표를 사용하여 인터프리터에게 문자열이라는 힌트를 줍니다.

>>> my_id = ‘monolith’

>>> print(my_id)

monolith

>>> my_id = “monolith”

>>> print(my_id)

monolith

여러 줄의 문자를 변수에 할당하고 싶을 때에는 엔터에 해당하는 관습적인 특수문자열인 \n을 사용할 수 있습니다. (아래 예제 코드에 구분하기 쉽도록 해당 특수 기호를 붉은 색으로 칠했습니다.)

>>> my_id = ‘monolith\nmy favorite number is 42’

>>> print(my_id)

monolith

my favorite number is 42

python에서는 특수하게 여러 줄의 문자를 특수기호를 사용하지 않고 변수에 할당하고 싶다면 아래와 같이 홑따옴표나 쌍따옴표를 연속으로 3개 붙여주면 됩니다.

>>> my_id = ‘’’monolith

my favorite number is 42’’’

>>> print(my_id)

monolith

my favorite number is 42

다만 홑따옴표와 쌍따옴표를 혼용해서는 안됩니다. 왜냐면 아래와 같은 방식으로 사용해야 하는 경우가 있기 때문입니다.

>>> my_script = ‘He shouted “Get out!”’

>>> print(my_script)

He shouted “Get out!”

숫자 값을 다루는 데이터 형은 정수형 (int)와 실수형 (float)으로 나뉩니다. C++ 등에서는 long integer나 double 등도 있으나 python에서는 길이 제약을 따로 두지 않습니다. python 인터프리터에 정수형이냐 실수형이냐 힌트는 숫자를 할당할 때, 소수점이 있는지 여부입니다. 참고로 #은 대부분의 컴퓨터 프로그래밍 언어에서 주석 (comment; 코딩한 내용이 컴퓨터가 실행가능한 코드로 변환될 때 제외되는 부분)을 나타낼 때 관습적으로 사용합니다.

>>> my_number = 42 #정수형

>>> my_number = 42.0 #실수형

그러면 정수형 값과 정수형 값을 나누는 것과 정수형 값과 실수형 값을 나누는 것은 어떻게 차이가 날지 보겠습니다.

>>> 42 / 2

21.0

>>> 42/2.0

21.0

둘 간 차이는 없습니다. python 2에서는 정수형 값들 간 나누기는 정수형 값을 인터프리터가 돌려주었으나 수학적으로 실수형 값으로 되돌려주는 것이 더 정확하기 때문에, 현재는 실수형 값을 되돌려줍니다. 곱셈도 마찬가지일까요?

>>> 21*2

42

>>> 21*2.0

42.0

정수형간 곱셈은 정수가 나오는 것이 수학적으로 옳기 때문에, 정수형으로 리턴합니다.

숫자형 값을 사용할 때, 유용한 것은 지수형을 사용하여 긴 값을 짧게 표현 할 수 있습니다.

>>> 1e4

10000.0

>>> 1e-4

0.0001

다만 1을 생략한 e4와 같은 표기는 변수 이름이나 함수 이름 등과 구분 할 수 없기 때문에 인터프리터가 받아주지 않습니다. 코딩을 잘 하기 위해서는 아래와 같은 오류 메시지를 절대 그냥 넘기지 말고 무슨 의미인지 파악하기 위해 정독하는 것이 필수입니다.

>>> e4

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

NameError: name 'e4' is not defined

python에서는 두 값이 같은지 여부를 확인하는 연산자 ==과 다른지 여부를 확인하는 연산자 != 가 있습니다.

>>> 2 == 2

True

>>> 10000.0 == 1e4

True

재밌는 것은 정수형인 10000은 실수형인 1e4와 당연하게도 같다고 봅니다.

>>> 10000 == 1e4

True

실수형으로 1.0으로 기입한 것은 인터프리터는 소수점 자리수를 표기한 것으로 보기 때문입니다.

아래처럼 정수형 1과 실수형 1.1간 비교는 당연히 다르다고 판단해줍니다.

>>> 1 == 1.1

False

실수형 값을 정수형 값으로 변환해 주는 함수로 int()라는 것이 있습니다.

>>> int(1.1)

1

그래서 실수형 값 1.1을 정수형으로 변환 후 1과 비교하면 당연히 같다고 판단합니다.

>>> 1 == int(1.1)

True

그러면 1.5나 1.6을 정수형으로 변환하면 어떻게 될까요?

>>> int(1.5)

1

>>> int(1.6)

1

'정수형으로 값을 변환하는 것은 두 정수 중에서 0에 가깝게 한다'

출처 입력

는 원칙이 수학적으로 옳기 때문에 인터프리터는 1.9는 1과 2 중에서 0에 가까운 1을 되돌려 줍니다. 그러므로 1과 int(1.9)는 같습니다.

소수점 첫째 자리에서 반올림을 하려면 (속칭 사사오입) int()함수가 아니라 round()함수를 사용하면 됩니다. 이 함수는 반올림 하려는 값과 소수점 몇 째 자리까지 남길 것 인가를 지정하는 인수(parameter)를 함께 넘겨주면 됩니다. 1.4를 소수점 첫째 자리에서 반올림 하려 한다면 아래와 같이 하면 됩니다.

>>> round(1.4, 0)

1.0

>>> round(1.5, 0)

2.0

python에서는 무리수 또한 지원을 합니다.

>>> 1 + 1j

(1+1j)

>>> 2 * (1 + 1j)

(2+2j)

다만 아래처럼 무리수 부분에 괄호로 두 수를 구분하지 않으면 인터프리터는 허수부를 그냥 더한 것으로 오해하기 때문에 주의해야 합니다.

>>> 2 * 1 + 1j

(2+1j)

아래처럼 무리수의 실수부와 허수부를 띄워쓰기 없이 붙여써도 마찬가지 결과입니다. 수학적으로 연산자 우선순위를 피하기 위한 구분은 괄호를 쓰는 것을 기본 원칙으로 하기 때문입니다.

>>> 2 * 1+1j

(2+1j)

무리수간 곱셈 연산도 당연히 가능합니다.

>>> (2+1j)*(2+1j)

(3+4j)

>>> (2+1j)*(2-1j)

(5+0j)

이제는 코딩에서 데이터 형을 사용하는 이유를 좀 더 포괄적으로 말해보겠습니다. 1960년대 미의회는 인공지능 (AI) 학회에 인공지능이 사람의 언어를 이해할 수 있을지를 문의 합니다. 인공지능 학회의 답변은 불가능하다 였습니다. 그 이유는 컴퓨터 프로그래밍 언어는 문맥 자유 문법 (Context free grammar)을 기초로 한 것이기 때문에 인간의 언어를 이해할 수 없다는 것이고 그래서 인간이 구축한 지식을 습득하여 포괄적인 지적능력을 갖출 수 없다는 결론이 나옵니다.

예를 들어, 어떤 사람이 '사과'라는 단어를 갑자기 말하면 그 말을 한 사람 (화자)과 듣는 사람 (청자)간 동일한 것을 연상할 수도 있지만 대다수는 제 각각 다른 대상을 떠올리기 일쑤입니다. 누군가는 어떤 잘못에 대한 뉘우침으로 하는 말을 하는 것으로 생각하겠지만, 또다른 누군가는 과일을 말하는 것으로 생각 할 수도 있습니다. 혹은 과일을 떠올린 사람들도 제 각각인게, 누군가는 거기서 한발 더 나아가 'Big apple'이라 불리는 뉴욕을 떠올릴 수도, 누군가는 컴퓨터 및 스마트폰 브랜드인 애플사를, 앨런 튜닝의 일화를, 백설공주가 깨어문 사과를, 혹은 누군가는 성서 속 선악과를 떠올릴 수도 있습니다. 그래서 우리는 해당 말을 한 사람이 앞서 혹은 이어서 하는 말을 듣고서야 무엇을 말하는지 파악할 수 있습니다. 그리고 문맥에 따라 반응하게 되는 것입니다.

컴퓨터 프로그래밍언어는 문맥을 다룰 능력이 없기 때문에 우리가 코딩에서 사용하는 값이 무엇인지 정확하게 지칭 (C, C++, Java, C#, Type script 등과 같은 언어)하거나 적당하게 힌트를 주거나 (python, R, Basic 등과 같은 언어) 하게 됩니다. 즉 * 라는 연산자를 사용했을 때, 이 것이 숫자의 곱셈을 뜻하는 것인지 문자열의 반복을 뜻하는 것인지, 혹은 + 연산자를 사용했을 때 이 것이 숫자의 덧셈을 뜻하는 것인지 두 문자열의 결합을 뜻하는 것인지 데이터 타입이 없다면 컴퓨터는 판단을 내릴 수 없습니다. 오로지 데이터 타입에 따라 행동을 달리 합니다. 이 것을 객체지향 기술에서 다형성 (polymorphism)이라 하고 기본적으로 데이터 타입에 따라 동일한 연산자 혹은 함수가 다르게 처리하도록 하게하는 객체지향 기술에서 가장 핵심이 되는 것입니다.

위의 AI에 관한 것으로 다시 돌아가서 그러므로, 컴퓨터가 인간의 어떤 메시지든 지식이든 다루는 것에 대한 문맥을 파악할 수 없어 인간의 지적 능력을 뛰어넘는 general AI가 나올 수 없습니다. 그래서 터미네이터 속 세상은 올 수 없습니다. 다만 이 것과 기계가 사고 (생각)을 하느냐는 다른 것입니다. 기계는 당연히 사고를 합니다. 이에 대해서는 나중에 다시 다루도록 하겠습니다.

#python #파이썬 #코딩 #coding #code #데이터타입 #데이터형 #datatype



댓글 없음:

댓글 쓰기