SERIE AI-NATIVE · NÚMEROS EN CUATRO EDADES, EPISODIO 4 DE 4 · EDAD 20
Número vs representación: La primera abstracción que usa todo programador (a los 20)
Resumen en un minuto
¿De qué trata esto? Un ensayo de ingeniería dirigido a veinteañeros. La idea que un niño descubre al contar manzanas y piedras —que un número no es su nombre— es la misma abstracción detrás de los tipos de datos abstractos, las codificaciones, el punto flotante y los dígitos Unicode.
Por qué es importante. Los errores aparecen justo en el espacio entre el valor y la codificación: ese 0.1 + 0.2 que no da 0.3, un byte que puede ser 251 o −5 según quién lo interprete, una columna de hoja de cálculo en base 26 sin cero. Decidir a qué capa pertenece cada dato es una decisión de ingeniería que tomas todos los días.
Qué puedes hacer después de leer. Escribe un convertidor que recorra cada número por tres codificaciones distintas y supere la prueba de invariancia; encuentra un error en tu propio código que dependa de la representación, y luego enseña la demostración del valor posicional a un joven de 15 años.
Numbers at Four Ages — la espina de la serie
▶ Véalo en marcha: abra la demo en vivo pública · sin registro
- Edad 7 · ¿Qué es un número? episodio 1
- Edad 11 · ¿Por qué existen tantas maneras de escribir los números? episodio 2
- Edad 15 · Diez símbolos, todos los números episodio 3
- Edad 20 · Número vs representación este episodio
La pregunta clave: ¿Por qué todo programador necesita distinguir entre un número y su representación?
Este episodio NO enseña la demostración del valor posicional; esa está en episodio 3 (edad 15). Las cantidades continuas (medir en vez de contar) serán tema de la próxima temporada.
De qué va este episodio: número vs representación
Este texto es un ensayo dirigido a veinteañeros sobre la diferencia entre un valor y la forma en que se escribe o almacena. Es para quienes ya programan o están por empezar. Solo necesitas una computadora portátil con Python y quince minutos para el ejercicio.
Es el episodio 4 de cuatro, y cierra el loop.
- Episodio 1 mostró a un niño de 7 años que cinco manzanas y cinco piedras tienen algo en común, y que "5" es solo su nombre.
- Episodio 2 permitió que un chico de 11 años inventara sistemas numéricos y descubriera por qué la notación posicional termina ganando.
- Episodio 3 le dio a un joven de 15 años la demostración de que todo número tiene exactamente una forma de escribirse en cualquier base, con o sin cero.
Este episodio muestra que la intuición infantil es la primera abstracción que usa cualquier programador. Las ideas siguen un capítulo de 陈诗峰 (Shifeng Chen), coautor de esta serie, sobre los números y sus representaciones. Llevadas un paso más allá, se convierten en una prueba que puedes ejecutar sobre tu propio código.
La serie se apoya en una imagen de la cocina, subiendo peldaños: huevos en un bol, un restaurante, un almacén de comida rápida. Aquí llegamos al último escalón: una cadena nacional de suministro de alimentos. Una caja con 42 cartones pasa por una docena de sistemas. Un código de barras la codifica de una forma, la base de datos del almacén la guarda como un entero binario, una exportación CSV escribe la cadena "0042" y una hoja de cálculo la mantiene en la columna AP. La cantidad nunca cambia; cada sistema la escribe de forma distinta. Los errores en la cadena de suministro viven justo en ese hueco.
Antes de seguir leyendo. Terminarás guiando a un joven de 15 años por la demostración de unicidad del episodio 3. Lee como quien tendrá que explicarlo. En 39 estudios, enseñar después de estudiar con esa expectativa obtuvo g = 0.48, y enseñar sin esa expectativa obtuvo g = −0.02 (Kobayashi (2024), Educational Psychology Review (ERIC EJ1414484)).
Actividad 1 · Cuenta hasta 31 con una sola mano (primero invéntalo)
Tu mano cuenta de 0 a 5 si cada dedo levantado vale uno. Sin mirar la solución, inventa una forma de contar hasta 31 con esa sola mano, de modo que cada número del 0 al 31 tenga su propio patrón de dedos y nunca repitas uno.
Luego usa tu sistema para mostrar el 19 y el 31. Escribe la regla que inventaste.
Si cada dedo vale el doble que el anterior (1, 2, 4, 8, 16), acabas de inventar el sistema binario. 19 es 16 + 2 + 1, y 31 son los cinco dedos levantados. Con la misma mano y el mismo número de dedos, tienes seis veces más alcance. Cambiaste la representación, pero los números no cambiaron en absoluto. Todo el ensayo se resume en ese gesto.
"Mismo número" se define por emparejamiento; una representación es una codificación
El juego de las manzanas del episodio 1 no es una simplificación para niños. Es la definición de "mismo número" sobre la que Frege construyó la aritmética. En los fundamentos de las matemáticas, dos colecciones tienen el mismo número exactamente cuando existe una correspondencia uno a uno entre ellas. Esto es el principio de Hume, en la raíz de la construcción de la aritmética de Frege en 1884 (Zalta, Stanford Encyclopedia of Philosophy, "Frege's Theorem and Foundations for Arithmetic"). En esa definición no se mencionan dígitos.
A representación es una codificación de ese valor: una cadena finita sobre algún alfabeto más una regla para leerla. Base diez, binario, números romanos, palitos y los bits en un registro son todas representaciones. La ingeniería de software nombra la misma separación: un tipo abstracto de datos es lo que hace un valor, independientemente de cómo se almacene; esta idea fue presentada en 1974 (Liskov & Zilles (1974), "Programming with abstract data types", ACM SIGPLAN Notices). Un número es el tipo abstracto de datos por excelencia, y cada sistema de numeración es solo una de sus implementaciones.
Una propiedad que permanece verdadera en cualquier codificación es un invariante del valor. Saber distinguir invariantes de hechos propios de la codificación es justo la habilidad que se entrena en este ensayo. Puedes practicarlo ahora mismo en el Number Playground, una página gratuita que muestra cualquier número de nueve formas distintas y te deja jugar al juego de ordenamiento de Chen.
La idea central de la serie, resumida en una frase: un número es el valor; una representación, una codificación; y el código correcto solo depende del valor.
Por qué triunfó la notación posicional: un código de longitud logarítmica con un alfabeto fijo
El capítulo de Chen es, en el fondo, una historia de compresión, y un ingeniero puede decirlo con precisión.
- Un conteo necesita n marcas para n: la longitud crece de forma lineal.
- Los sistemas aditivos (romano, egipcio) son más breves, pero exigen nuevos símbolos a medida que los números aumentan. Los egipcios tenían un solo signo para un millón, pero nada más allá: ahí se acababa el camino.
- La notación posicional en base b solo requiere 1 + ⌊log_b n⌋ dígitos (Weisstein, MathWorld, "Digit"). La longitud es logarítmica respecto al valor, y el alfabeto nunca crece.
Como lo resume Chen: el valor posicional transforma el infinito de símbolos en un infinito de lugares.
Ese beneficio tiene un costo: hay que conservar cada posición, incluso las vacías, y para eso existe el cero como marcador de posición. Sin embargo, el cero no es estrictamente necesario. En bijectiva (base k sin ceros) los dígitos van del 1 al k. Todo entero positivo sigue teniendo exactamente una cadena, y la cadena vacía representa el cero. Usas esto todos los días: las columnas de una hoja de cálculo, de la A a la Z, luego AA, AB…, son base 26 bijectiva. Excel permite 16,384 columnas, y la última es XFD (Microsoft, "Excel specifications and limits"): 24 × 26² + 6 × 26 + 4 = 16,384.
Actividad 2 · Escribe el convertidor y prueba qué no debe cambiar
Escribe tres codificadores y sus decodificadores antes de mirar la versión de abajo: base b con dígito cero, base diez sin ceros (dígitos del 1 al 9 y κ para el diez, el símbolo de Chen), y etiquetas de columnas de hoja de cálculo. Después, escribe pruebas de propiedades. Deben comprobar que cada codificación recorre ida y vuelta sin perder información, y deben detectar cualquier “hecho” que solo se cumpla en una representación.
Una versión que supera todas las aserciones al ejecutarse:
DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"
def to_base(n, b):
if n == 0:
return "0"
out = ""
while n:
n, r = divmod(n, b)
out = DIGITS[r] + out
return out
def from_base(s, b):
return int(s, b)
def to_zero_free_ten(n): # digits 1-9 and κ (ten); no 0
out = ""
while n:
r = n % 10 or 10
out = "123456789κ"[r - 1] + out
n = (n - r) // 10
return out
def from_zero_free_ten(s):
n = 0
for ch in s:
n = n * 10 + "123456789κ".index(ch) + 1
return n
def column_label(n): # spreadsheet columns: zero-free base 26
out = ""
while n:
r = n % 26 or 26
out = chr(64 + r) + out
n = (n - r) // 26
return out
def column_number(s):
n = 0
for ch in s:
n = n * 26 + ord(ch) - 64
return n
assert to_zero_free_ten(3020) == "2κ1κ" and to_zero_free_ten(10**6) == "99999κ"
assert column_label(27) == "AA" and column_label(16384) == "XFD"
for n in range(1, 10_000): # every encoding round-trips: the value is untouched
assert from_base(to_base(n, 3), 3) == n
assert from_zero_free_ten(to_zero_free_ten(n)) == n
assert column_number(column_label(n)) == n
assert (n % 3 == 0) == to_base(n, 3).endswith("0") # true in base 3 ...
assert any((n % 3 == 0) != str(n).endswith("0") for n in range(1, 100)) # ... false in base ten: a fact about notation
Fíjate en las dos últimas aserciones. “Ser divisible por 3 significa que el último dígito es 0” se cumple para todo número en base 3, y la última línea muestra que falla en base diez (3 es divisible por 3 y termina en 3). Una propiedad que se cumple en una codificación y falla en otra pertenece a la codificación, no al número. El experimento de clasificación de Chen, donde los niños deciden si una frase trata sobre el número o sobre cómo se escribe, es el mismo razonamiento que una prueba de propiedad que mantiene fijo el valor y cambia la codificación. En base b, el atajo de la suma de dígitos funciona exactamente para los divisores de b − 1 (Weisstein, MathWorld, "Divisibility Tests"), así que la regla conocida para 3 y 9 es un hecho sobre el diez, no sobre el tres.
Los mismos bits, números distintos: el problema en el código
Tres ejemplos que puedes reproducir en un prompt de Python. Cada uno muestra un hecho de representación filtrándose a la capa de valor.
- Un byte, dos números. El patrón de bits 11111011 llega a un bar, y el bartender pregunta: “¿251 o −5?” Es 251 leído como byte sin signo y −5 leído como entero de 8 bits en complemento a dos. Los bits son idénticos; la codificación acordada decide el número. Los errores aparecen cuando dos sistemas no se ponen de acuerdo sobre la codificación.
- 0.1 + 0.2 es 0.30000000000000004. Un float binario no puede representar exactamente una décima, igual que un decimal no puede representar exactamente un tercio. En base 3, un tercio es simplemente 0.1. El valor es correcto; la codificación lo redondea.
0.1 + 0.2 == 0.3es una cuestión de codificaciones, por eso el código numérico compara usando una tolerancia. - Cinco caracteres, un valor. Los caracteres 5, ٥, ५, Ⅴ y 五 tienen todos el valor numérico 5 en la base de datos de caracteres Unicode (Unicode Character Database (UnicodeData.txt) y Unihan (U+4E94)). Python's
int("٥")yint("५")devuelven 5, porque esos son dígitos decimales en Unicode, mientras queint("五")yint("Ⅴ")lanza ValueError, por diseño:intlee dígitos, no numerales.unicodedata.numeric("五")devuelve 5.0. Todo analizador traza esta línea en algún punto; el error es hacerlo sin darse cuenta.
La versión para la cadena de suministro: un código de producto "0042" que se carga en una hoja de cálculo se convierte en el número 42, y los ceros iniciales que formaban parte del identificador desaparecen. En algún almacén, ahora creen que el producto 0042 (patitos de hule) y el producto 42 (también patitos de hule, pero de otro proveedor) son lo mismo, y terminan pidiendo el doble de patitos. Ese código era un identificador guardado como una cadena de dígitos, nunca una cantidad. Saber en qué capa vive un valor habría evitado el problema.
Un esquema con una predicción: ¿un número tiene cuerpo?
La serie toma una perspectiva de las notas de "ingeniería lúdica" de Paul, probada en vez de asumida: un cuerpo tiene espíritu, huesos, carne y piel. En un sistema numérico:
- el espíritu es el valor;
- el hueso es el marco posicional, la estructura del tipo;
- la carne son los algoritmos sobre los numerales (llevadas, comparación, análisis);
- la piel son los glifos y los bytes.
La predicción que lo hace útil: todo lo que sobrevive a un cambio de codificación pertenece al valor; todo lo que se rompe pertenece a una capa de implementación. Sumar es espíritu; la regla de llevada es carne: una sola regla con N en ella ("cuando llegues a N, lleva uno"), así que cambiar la base solo cambia la N, pero la suma nunca cambia. En código, la regla es: "prueba propiedades en la capa de valor y mantén los hechos específicos de la codificación detrás de la interfaz de la codificación".
Donde el esquema deja de funcionar:
- Puedes cambiar los huesos (cambiar la base) y mantener el espíritu, cosa que ningún cuerpo permite.
- "Discreto frente a continuo" es un eje, no una capa. Aristóteles lo planteó así: "La cantidad es o discreta o continua." (Aristóteles, Categorías, Parte 6, trad. E. M. Edghill (MIT Internet Classics Archive)). Todo aquí es discreto; medir, y con ello los floats bien hechos, queda para la próxima temporada.
- Si el espíritu existe por sí mismo es una cuestión abierta. Según la visión platonista, los números existen, son abstractos y no dependen de ninguna mente (Linnebo, Stanford Encyclopedia of Philosophy, "Platonism in the Philosophy of Mathematics"). Según la visión nominalista, no existen objetos numéricos abstractos en absoluto (Bueno, Stanford Encyclopedia of Philosophy, "Nominalism in the Philosophy of Mathematics"). Como ingeniero, puedes mantenerte agnóstico: lo que importa es la interfaz. Eso ya es una postura filosófica, y además funcional.
Por qué una sola idea sirve para todas las edades
Esta serie apuesta por una idea que suele atribuirse a Jerome Bruner en The Process of Education (1960): que cualquier materia puede enseñarse de forma intelectualmente honesta en cualquier etapa del desarrollo. Lo parafraseamos a propósito. No pudimos comprobar la cita original, así que no la citamos.
La prueba de lo "honesto" es el mismo test de invariancia. Cada episodio repite el mismo núcleo, y nada de lo que aprende aquí un niño de 7 años tiene que desaprenderlo a los veinte. El juego de emparejar es el principio de Hume. "5 es solo un nombre" es la separación entre valor y representación. El contador a dos manos es la regla del acarreo.
El manual detrás de la serie se apoya en estudios comprobables:
- La memoria de trabajo retiene de tres a cinco elementos (Cowan (2001), "The magical number 4 in short-term memory", Behavioral and Brain Sciences 24).
- El apoyo que ayuda a principiantes puede estorbar a expertos (Kalyuga, Ayres, Chandler & Sweller (2003), "The Expertise Reversal Effect", Educational Psychologist 38).
- Anticipar que tendrás que enseñar es lo que realmente hace que enseñar valga la pena (Kobayashi (2024), Educational Psychology Review (ERIC EJ1414484)).
Te comparto una perspectiva personal. Sostengo que la Verdad, el Amor y la Belleza no son tres ideales separados, sino tres facetas de una misma Realidad, y en mi fe, de una sola Persona. En esta serie también funcionan como una lista de verificación para ingenieros, válida incluso sin el componente espiritual. Una lección debe ser verdadera (que quien aprende pueda comprobarla), amorosa (escrita para alguien concreto y que lo acompañe en sus errores), y bella (que contenga al menos un momento digno de compartirse).
- La verdad sin amor es una demostración correcta que nadie logra seguir.
- El amor sin verdad es un juego entretenido que siembra una falsedad.
- La belleza sin las otras dos es solo una infografía bonita con la historia equivocada.
Errores que son parcialmente ciertos
- "0.1 is stored wrong." (Traducción: "0.1 se almacena mal.") Se almacena como la fracción binaria más cercana, exactamente como está especificado. La sorpresa está en la codificación, no en un error, y la solución es comparar con una tolerancia o usar un tipo decimal.
- "Leading zeros don't matter." (Traducción: "Los ceros a la izquierda no importan.") Es cierto para una cantidad, pero falso para un identificador. "0042" como código de producto es una cadena que simplemente contiene dígitos.
- "Base 26 column labels are just letters." (Traducción: "Las etiquetas de columna en base 26 son solo letras.") Son un sistema de numeración posicional sin dígito cero; por eso después de la Z viene AA, no BA.
Ahora ponlo en práctica
Tu turno de enseñar. Busca a un joven de 15 años y repasen juntos "La demostración: cada número tiene exactamente una escritura" en el episodio 3 con esa persona. No le des los pasos escritos: pregúntale cuál es el residuo cuando 352 se divide entre 3, luego qué pasa con el cociente, y deja que vea que nadie eligió los dígitos.
¿Qué debe lograr? Que el joven de 15 años escriba los pasos de los residuos para 352 en base 3 sin ayuda (111001) y explique en una frase por qué el último dígito está forzado. Publica su edad y resultado como comentario en este artículo.
Por qué importa: los cinco porqués
El problema: una canalización de datos elimina los ceros iniciales de los códigos de producto, así que 0042 y 42 se fusionan y dos productos se convierten en uno solo.
- ¿Por qué se fusionaron los códigos? Un cargador interpretó "0042" como el número 42. Ambas cadenas terminan representando el mismo valor, así que los identificadores se mezclaron.
- ¿Por qué se interpretó como número? El tipo se dedujo por la apariencia de los caracteres (solo dígitos), en vez de por el significado real del campo.
- ¿Por qué deducirlo por la apariencia? Porque el sistema trató la representación (una cadena de dígitos) como si fuera el valor, justo la confusión que el capítulo de Chen enseña a evitar desde niños.
- ¿Por qué no se detectó? Ninguna prueba mantuvo el valor fijo mientras cambiaba la codificación. Una prueba que mantuviera el valor fijo y cambiara la codificación fallaría de inmediato, igual que la línea de contraste en base diez del convertidor muestra cómo un "hecho" de base 3 deja de cumplirse en base diez.
- Causa raíz: el código dependía de la capa de representación, no de la capa de valor. La solución es la regla del episodio: decide primero cuál es el valor (cantidad o identificador), mantén los hechos de codificación detrás de una interfaz (Liskov & Zilles (1974), "Programming with abstract data types", ACM SIGPLAN Notices), y prueba la invariancia entre codificaciones.
Ponlo en práctica esta semana
- Lee la línea de preparación para enseñar.
- Cuenta hasta 31 con una sola mano (2 minutos).
- Escribe los tres conversores y las pruebas de propiedades, luego compáralos con la versión de arriba (15 minutos).
- Abre el Number Playground. Escribe 16384 y 1000000, revisa tu conversor con sus filas (incluida la fila de columnas de hoja de cálculo: 16384 es XFD), y luego juega el juego N-o-R.
- Encuentra un lugar en tu propio código donde un hecho dependa de la representación (cadena vs número, igualdad de flotantes, un parser que solo acepte dígitos). Añade una prueba de invariancia.
- Enseña la demostración del episodio 3 a un joven de 15 años.
¿Cómo saber si funcionó?
- Tu conversor pasa todas las pruebas anteriores.
- Tu propio código tiene una nueva prueba de propiedad que fallaría si un hecho de representación se filtrara a la capa de valor.
- Puedes explicar, en una frase cada uno, por qué 11111011 son dos números, por qué 0.1 + 0.2 ≠ 0.3 en flotantes binarios, y por qué a la Z le sigue AA.
Vuelve a evaluarte después de una semana. Hacer pruebas supera a releer a los 7 días (Roediger & Karpicke (2006), "Test-Enhanced Learning", Psychological Science 17). Lo que esto no puede medir: si el hábito se mantiene bajo presión de entrega. La prueba de propiedades en CI sí lo detecta.
Feedforward: trampas anticipadas
- Si un campo contiene solo dígitos, decide primero si representa una cantidad o un identificador. Escribe esa decisión en el esquema antes de que el cargador lo infiera.
- Si comparas floats con
==, detente. Usa una tolerancia o un tipo decimal, y añade una prueba con 0.1 + 0.2. - Si tu parser se encuentra con ٥ o 五, decide conscientemente: Python's
intacepta dígitos decimales Unicode como ٥ y rechaza numerales como 五 y Ⅴ por diseño. Escribe cuáles acepta tu sistema y pruébalo.
Verdad, amor y belleza en este episodio
- Verdad: todas las afirmaciones se pueden comprobar. El convertidor pasa los asserts, y los ejemplos de byte y float se reproducen en cualquier prompt de Python.
- Amor: el ensayo te pone en las manos a un joven de 15 años para enseñar, y enfrenta cada error común con lo que sí acierta.
- Belleza: una sola idea, desde cinco manzanas hasta la última columna de Excel, se sostiene a cualquier edad sin que haya que desaprender nada. (El huevo que se dio la mano con una piedra en el episodio 1 ahora es el cartón 0042 en un camión nacional. Su cuenta sigue siendo una; solo su nombre cambia una y otra vez.)
Autoevaluación 5S
| S | Afirmación | Evidencia |
|---|---|---|
| Simple | El texto está escrito para que se lea con facilidad, a un nivel equivalente a grado 13 o inferior. | Índice Flesch–Kincaid del texto: 8.4 (banda ≤ 13), recalculado por node scripts/check-numbers-four-ages.mjs |
| Sólido | Las definiciones y los datos tienen fuente; el código se ejecuta correctamente. | columnas de Excel16,384 (Microsoft); principio de Hume |
| Agudo | La notación posicional es un código de longitud logarítmica con alfabeto fijo; el código correcto solo depende del valor. | Longitud logarítmica · la prueba de propiedades |
| SMART | Esta semana: escribe el convertidor, añade una prueba de invarianza en tu propio código y enseña el concepto a alguien más. | Poner en práctica · Playground |
| Sorpresa | Tu hoja de cálculo siempre ha contado en base 26 sin ceros. | XFD = 16,384 |
| Verdad · Amor · Belleza | Afirmaciones comprobables; una persona a quien enseñar; una idea que se sostiene a cualquier edad. | Verdad, amor y belleza |
Fuentes
- 陈诗峰 (Shifeng Chen), borrador del capítulo 《第一章 数和数的表示形式》 ("Numbers and Their Representations"), 2026. Lee el capítulo original (PDF, en chino). Coautor de esta serie.
- Zalta, E. N. "Frege's Theorem and Foundations for Arithmetic." Stanford Encyclopedia of Philosophy. plato.stanford.edu
- Liskov, B. & Zilles, S. (1974). Programming with abstract data types. ACM SIGPLAN Notices. Crossref 10.1145/942572.807045
- Weisstein, E. W. "Digit." MathWorld. mathworld.wolfram.com
- Weisstein, E. W. "Divisibility Tests." MathWorld. mathworld.wolfram.com
- Microsoft. "Excel specifications and limits." support.microsoft.com
- Unicode Character Database, UnicodeData.txt. unicode.org
- Aristóteles. Categorías, Parte 6, trad. E. M. Edghill. classics.mit.edu
- Linnebo, Ø. "Platonism in the Philosophy of Mathematics." Stanford Encyclopedia of Philosophy. plato.stanford.edu
- Bueno, O. "Nominalism in the Philosophy of Mathematics." Stanford Encyclopedia of Philosophy. plato.stanford.edu
- Cowan, N. (2001). El número mágico 4 en la memoria a corto plazo. Behavioral and Brain Sciences 24. doi:10.1017/S0140525X01003922
- Kalyuga, S., Ayres, P., Chandler, P. y Sweller, J. (2003). El efecto de reversión de la experiencia. Educational Psychologist 38. doi:10.1207/S15326985EP3801_4
- Kobayashi, K. (2024). Efectos del aprendizaje interactivo al prepararse para enseñar y al enseñar. Educational Psychology Review. ERIC EJ1414484
- Roediger, H. L. y Karpicke, J. D. (2006). Aprendizaje mejorado por pruebas. Psychological Science 17. doi:10.1111/j.1467-9280.2006.01693.x
- DeLamater, M. (1999), sobre la hipótesis de Bruner. Education Week. edweek.org (secundario; no se comprobó la redacción original)