13.1. Introducción a los números romanos
En capítulos interiores, se “sumergió” dando un vistazo
rápido al código e intentándo comprenderlo lo más rápidamente posible.
Ahora que tiene bastante Python a sus espaldas, vamos a retroceder y ver
los pasos que se dan antes de escribir el
código.
En los próximos capítulos vamos a escribir, depurar y optimizar una
serie de funciones de utilidad para convertir números romanos a decimales,
y viceversa. Vimos el mecanismo de construir y validar los números romanos
en Sección 7.3, “Caso de estudio: números romanos”, pero ahora retrocederemos y consideraremos
lo que tomaría expandirlo en una utilidad de doble sentido.
Las reglas de los números romanos
llevan a varias observaciones interesantes:
- Sólo hay una manera correcta de representar un número en
particular en romanos.
- A la inversa también es cierto: si una cadena de
caracteres es un número romano válido, representa un número único (es decir
sólo se puede leer de una manera).
- Hay una cantidad limitada de números expresables en
romanos, específicamente desde 1 a
3999. (Los romanos tenían varias maneras de expresar
números más grandes, por ejemplo poniendo una barra sobre un número
representando que su valor normal debería multiplicarse por
1000, pero no vamos a tratar con eso. Para el propósito
de este capítulo, estipularemos que los números romanos van de
1 a 3999).
- No hay manera de representar 0 en números romanos.
(Sorprendentemente, los antiguos romanos no tenían concepto de 0 como
número. Los números eran para contar cosas que tenías; ¿cómo ibas a contar
lo que no tenías?)
- No hay manera de representar números negativos en
romanos.
- No hay manera de representar fracciones o números no
enteros en romanos.
Dado todo esto, ¿qué podríamos esperar de un conjunto de funciones
para convertir de y a números romanos?
Requisitos de roman.py
- toRoman debería devolver la representación en romanos de
todos los enteros del 1 al 3999.
- toRoman debería fallar cuando se le dé un entero fuera
del rango 1 al 3999.
- toRoman debería fallar cuando se le dé un número no
entero.
- fromRoman debería tomar un número romano válido y
devolver el número que representa.
- fromRoman debería fallar cuando se le dé un número
romano no válido.
- Si tomamos un número, lo convertimos a romanos, y luego de
vuelta a un número, deberíamos acabar con el mismo número con que
empezamos. Así que fromRoman(toRoman(n)) == n para
todo n en 1..3999.
- toRoman debería devolver siempre un número romano usando
letras mayúsculas.
- fromRoman sólo debería aceptar números romanos en
mayúsculas (es decir debería fallar si se le da una entrada en
minúsculas).
Lecturas complementarias
- Este sitio cuenta
más cosas sobre los números romanos, incluyendo una fascinante historia sobre la manera en que los
romanos y otras civilizaciones los usaban (versión corta: descuidada e
inconsistentemente).