`int` en Python: precisión arbitraria y cómo funciona realmente

En casi todos los lenguajes que conoces, un entero ocupa un bloque fijo de memoria: 32 bits, 64 bits, y listo. Si el número no cabe, tienes overflow y el resultado es silenciosamente incorrecto. Python rompe ese contrato por diseño: un int en Python puede ser tan grande como la memoria de tu máquina permita. No hay límite de rango, no hay overflow silencioso.

¿Cómo es posible? Porque int no es un tipo primitivo de bajo nivel: es un objeto Python implementado en CPython como una secuencia de “dígitos” en base 2³⁰ (30 bits por dígito). Cuando el número crece, CPython simplemente asigna más dígitos. Es básicamente aritmética de precisión arbitraria integrada en el lenguaje, no una librería externa.

Esto tiene consecuencias directas: operaciones como 2 ** 1000 funcionan y devuelven el número exacto. Lo usarás siempre que calcules factoriales grandes, trabajes con criptografía, o necesites resultados exactos sin pensar en rangos. El precio es velocidad y memoria: un int grande es más lento de operar que un int64 nativo, pero eso rara vez importa hasta que estás procesando millones de ellos en un loop crítico.

Hay una optimización de CPython que vale la pena entender para no confundirte cuando aparezca: el pool de enteros pequeños. CPython pre-crea y reutiliza los objetos enteros del rango −5 a 256. Eso significa que cuando escribes a = 256 y b = 256, ambas variables apuntan exactamente al mismo objeto en memoria. El operador is compara identidad de objeto (no valor), así que a is b da True. Pero con a = 257 y b = 257, CPython puede crear dos objetos distintos con el mismo valor, y a is b puede dar False. Digo “puede” porque el comportamiento exacto depende del contexto de ejecución (en el REPL versus en un módulo compilado puede variar). La regla de oro: nunca uses is para comparar enteros; usa ==.

Python también te deja escribir enteros en distintas bases numéricas con prefijos: 0b para binario, 0o para octal, 0x para hexadecimal. Y para números grandes, puedes usar _ como separador visual en cualquier posición; el intérprete lo ignora completamente.

# Precisión arbitraria: este número existe y es exacto
big = 2 ** 1000
print(big)
print(type(big))  # <class 'int'>, siempre

# El pool de enteros pequeños (CPython)
a = 256
b = 256
print(a is b)   # True  — mismo objeto del pool
print(a == b)   # True

c = 257
d = 257
print(c is d)   # False en muchos contextos — objetos distintos, mismo valor
print(c == d)   # True  — usa siempre == para comparar valores

# Bases numéricas con prefijos
en_binario  = 0b1010_1111   # 175 en decimal
en_octal    = 0o257         # 175 en decimal
en_hex      = 0xAF          # 175 en decimal

print(en_binario, en_octal, en_hex)  # 175 175 175
print(type(en_hex))                  # <class 'int'> — internamente es lo mismo

# Separadores de miles para legibilidad
poblacion_mundial = 8_100_000_000
presupuesto       = 1_500_000
mascara_bits      = 0xFF_FF_FF_FF    # también funciona en hex

print(poblacion_mundial)  # 8100000000
print(mascara_bits)       # 4294967295

Lo que hace cada decisión

El cálculo 2 ** 1000 funciona sin importar nada porque CPython expande la representación interna automáticamente. No hay nada que configurar, no hay tipo BigInteger que importar como en Java: el mismo int de siempre lo maneja.

Fíjate en que todos los literales de base distinta (0b1010_1111, 0o257, 0xAF) imprimen 175 y tienen type igual a int. Python no tiene tipos separados para “entero hexadecimal” o “entero binario”; la base es solo una notación de escritura en el código fuente. Esto significa que puedes mezclarlos en expresiones sin conversión: 0xFF + 0b0001 es perfectamente válido.

Los separadores _ son puramente visuales. 8_100_000_000 y 8100000000 son idénticos para el intérprete; el guión bajo solo ayuda a quien lee el código. Puedes ponerlos donde quieras —aunque lo razonable es cada tres dígitos decimales, o cada cuatro en hex para agrupar bytes.

El experimento con is y 257 es el que más confunde a principiantes: no es que Python sea inconsistente, es que is nunca fue la herramienta correcta para comparar valores. is te dice si dos variables apuntan al mismo objeto en memoria, que es una pregunta de implementación interna, no de lógica de tu programa.

Errores que debes conocer

Error: Usar is en vez de == para comparar enteros, confiando en que funciona porque los números pequeños están en el pool.

# ❌ Wrong
user_age = int(input("Edad: "))  # supón que el usuario escribe 300
if user_age is 300:              # SyntaxWarning en Python 3.8+, y puede fallar
    print("Tiene 300 años")

# ✅ Right
user_age = int(input("Edad: "))
if user_age == 300:
    print("Tiene 300 años")

== compara el valor matemático, que es lo que siempre quieres; is compara identidad de objeto, un detalle de implementación que no debes usar como condición de negocio.

Error: Asumir que un int de Python se comporta como un int32 o int64 de C cuando hay operaciones de bits en rangos altos.

# ❌ Wrong — esperando que haya overflow como en C
resultado = 2**31 + 2**31   # en C int32 esto sería overflow; en Python es 4294967296

# ✅ Right — si necesitas semántica de 32 bits sin signo, úsala explícitamente
import ctypes
resultado_32 = ctypes.c_uint32(2**31 + 2**31).value  # 0

Si estás haciendo operaciones de bajo nivel que dependen del comportamiento de overflow, necesitas ctypes u otro mecanismo; no puedes confiar en que Python lo imite.

20

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio