Python

파이썬 숫자의 자료형

총알 2024. 6. 7. 18:51
728x90

파이썬에서 숫자는 c언어에서와 마찬가지로 정수, 실수, 8진수, 16진수 등을 사용할 수 있다.

그럼 파이썬에서는 어떻게 자료형을 선언해서 사용하는지 확인해 보도록 하자.

 

우선 아래와 같이 숫자의 자료형을 선언하게 되어있다.

정수는 그냥 숫자를 대입, 실수는 소수점이 포함된 숫자, 8진수는 0oXX, 16진수는 0xXX와 같이 선언한다.

a = 16 #정수
b = 3.14 #실수
c = 0o10 #8진수
d = 0x20 #16진수

print("정수 :",a)
print("실수 :",b)
print("8진수 :",c)
print("16진수 :",d)

 

그럼 이어서 출력결과를 확인해보자.

출력 결과는 아래와 같이 나오게 된다.

정수 : 16  
실수 : 3.14
8진수 : 8  
16진수 : 32

 

그럼 이 숫자들의 자료형은 어떤 타입인지도 확인을 해보자.

a = 16 #정수
b = 3.14 #실수
c = 0o10 #8진수
d = 0x20 #16진수

print("정수 %d 의 type:" %a, type(a))
print("실수 %f 의 type:" %b, type(b))
print("8진수 %o 의 type:" %c, type(c))
print("16진수 %x 의 type:" %d, type(d))

 

 

숫자들은 print에서 아래와 같이 출력할 수 있다.

  print 출력 방법
정수 %d
실수 %f
8진수 %o
16진수 %x

 

그럼 이어서 출력 결과를 확인해 보자.

정수 16 의 type: <class 'int'>
실수 3.140000 의 type: <class 'float'>
8진수 10 의 type: <class 'int'>
16진수 20 의 type: <class 'int'>

정수, 8진수, 16진수의 자료형 타입은 int이고 실수의 자료형 타입은 float으로 설정된 것을 확인할 수이다.

그럼 C언어를 개발하던 나로서는 궁금하게 또 생겼다.

이 숫자들의 size는 어떻게 될까...?

역시 궁금한 건 해봐야 하지 않을까?

그래서 해봤다.

 

import sys

a = 16 #정수
b = 3.14 #실수
c = 0o10 #8진수
d = 0x20 #16진수

print("정수 %d 의 size:" %a, sys.getsizeof(a))
print("실수 %.3f 의 size:" %b, sys.getsizeof(b))
print("8진수 %o 의 size:" %c, sys.getsizeof(c))
print("16진수 %x 의 size:" %d, sys.getsizeof(d))

size를 확인하기 위해서는 sys module을 import 해줘야 한다.

sys모듈에서 getsizeof함수를 활용하면 되는 데 사용방법은 위 소스코드를 참조하도록 하자.

 

정수 16 의 size: 28
실수 3.140 의 size: 24
8진수 10 의 size: 28
16진수 20 의 size: 28

출력 결과는 위와 같다.

각 숫자의 Size는 위와 같이 출력되며 단위는 bytes이다.

C언어만 개발할 때는 이해할 수 없는 Size의 크기인데 왜 이런 size가 나오는지 확인해 봤다.

 

아래 링크에 접속하면 정수 객체에 관련된 정보를 얻을 수 있다.

https://docs.python.org/ko/3/c-api/long.html

 

모든 정수는 위와 같은 PyLongObject의 객체 구조를 따르게 되어있는데 해당 자료를 확인하기 위해서는

아래 링크에 접속해서 Cpython의 소스코드를 무료로 다운받아서 확인하면 된다.

https://github.com/python/cpython

 

나의 PC에는 Git이 설치되어있지 않아서 빨간색으로 표시한 항목으로 소스코드를 다운받았다.

 

<pytypedefs.h>

typedef struct _longobject PyLongObject;
typedef struct _object PyObject;
################################################################
<longintrepr.h>

struct _longobject {
    PyObject_HEAD
    _PyLongValue long_value;
};

typedef struct _PyLongValue {
    uintptr_t lv_tag; /* Number of digits, sign and flags */
    digit ob_digit[1];
} _PyLongValue;

################################################################
<object.h>

#define PyObject_HEAD                   PyObject ob_base;

struct _object {
    Py_ssize_t ob_refcnt;
    PyTypeObject *ob_type;
};

################################################################
#최종적으로는 아래와 같은 구조를 갖는다.
struct _longobject {
    Py_ssize_t ob_refcnt;
    PyTypeObject *ob_type;
    uintptr_t lv_tag; /* Number of digits, sign and flags */
    digit ob_digit[1];
};

ob_refcnt: 해당 자료형의 참조 횟수
*ob_type: 해당 객체 타입의 정보와 메소드 정보를 가르키를 포인터
lv_tag: 해당 자료형을 표현하기 위한 배열의 개수
ob_digit[1]: 해당 자료형의 값

 

위의 내용을 정리하면 결국 아래와 같은 데이터 구조를 갖는다.

 

C언어와 다르게 굉장히 특이한 구조를 갖고 있는데 배열의 size가 4바이트 단위이고 최대 3F FF FF FF를 갖는다.

그래서 2^30의 경우 2개의 배열이 필요하고 size가 4바이트 늘어나는데 진짜 늘어나는지 확인해 보도록 하자.

 

import sys

a = 2**30-1
b = 2**30

print("정수 %d 의 size:" %a, sys.getsizeof(a))
print("정수 %d 의 size:" %b, sys.getsizeof(b))

**는 거듭제곱을 의미한다 2**30은 2^30과 동일하다.

 

정수 1073741823 의 size: 28
정수 1073741824 의 size: 32

출력결과는 위와 같다.

앞서 설명한 것과 같이 2^30에서 size가 4 증가한 것을 확인할 수 있다.

 

여기까지 숫자의 자료형에 관련해서 알아봤는데,

가볍게 알아보려고 했는데 생각보다 깊게 알아보게 된 것 같다.

728x90