Comunidad de diseño web y desarrollo en internet online

Convertir números romanos en arábigos con Actionscript 3

Hace poco me hizo falta, para la realización de un proyecto educativo, tener la posibilidad de convertir de números arábigos a números romanos y viceversa, por lo que para lograrlo realicé una clase en ActionScript 3 que realiza esta tarea.

Aunque los números romanos ya están en desuso y es muy extraño que hoy en día alguien requiera utilizarlos he decidido compartir esta clase con la comunidad, quizás haya alguien que le sirva de ayuda la misma.

Esta clase asume que no se requerirá trabajar con números mayores de 3'999'999 por lo que cualquier valor que sobrepase esta cantidad arribará en un error de ejecución, para los números mayores de 3999 se utilizó la notación de entre paréntesis para indicar que la base de multiplicación es 1000.

Aquí tienen el contenido de la clase ubicada en el package ecn.format

Código :

package ecn.format {

public class RomanNumbers {

protected static const _letters:Array = ["I", "V", "X", "L", "C", "D", "M", "(V)", "(X)", "(L)", "(C)", "(D)", "(M)"];
protected static const _regexp:RegExp = /^((\(M\)){0,3})(\(C\)\(M\)|\(C\)\(D\)|(\(D\))?(\(C\)){0,3})(\(X\)\(C\)|\(X\)\(L\)|(\(L\))?(\(X\)){0,3})(M\(X\)|M\(V\)|(\(V\))?)(M{0,3})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;

//---Método de hacer un test del número romano
public static function testRoman(roman:String):Boolean {
return _regexp.test(roman);
}

//---Método de obtener un número romano
public static function getRomanNumber(number:uint):String {

if (number > 3999999) trace(new Error("Numbers higher than 3999999 can't be converted to Roman. Try lower value!"));

var roman:String = "";
var cant:uint = String(number).length;
var narray:Array = String(number).split("").reverse();

var parser:Function = function(item:String, index:int, a:Array):void {

switch (item) {

case "0":
case "1":
case "2":
case "3":
roman = repeat(_letters[index * 2], uint(item)) + roman;
break;

case "4":
roman = (_letters[index * 2] + _letters[index * 2 + 1]) + roman;
break;

case "5":
case "6":
case "7":
case "8":
roman = _letters[index * 2 + 1] + repeat(_letters[index * 2], uint(item) - 5) + roman;
break;

case "9":
roman = _letters[index * 2] + _letters[index * 2 + 2] + roman;
break;

}

}

narray.forEach(parser);

return roman;

}

//---Método de obtener el número arábigo
public static function getArabicNumber(roman:String):uint {

if (!testRoman(roman)) trace(new Error("You enter an invalid roman number. Please try with another value"));

var reg:RegExp = /(\()(\w)(\))/g;
var simple:String;
var values:uint = 0;
var array:Array = _regexp.exec(roman);

array.splice(0, 1);
array.splice(1, 1);
array.splice(2, 2);
array.splice(3, 2);
array.splice(4, 1);

var parser:Function = function(item:String, index:int, a:Array):void {

switch(index){

case 0:
case 1:
case 2:
simple = item.replace(reg, "$2");
values += getValue(simple) * 1000;
break;

case 3:
simple = item.replace(reg, "$2");
values += ((simple.slice(0, 1) == "M") ? getValue(simple.slice(1, 2)) * 1000 - getValue(simple.slice(0, 1)) : getValue(simple) * 1000);
break;

case 4:
case 5:
case 6:
case 7:
values += getValue(item);
break;

}

}

array.forEach(parser);

return values;
}

//---Función de devolver un número a partir de un string romano
protected static function getValue(str:String):uint {

var cant:uint = str.length;
var chars:Array;
var ret:uint;

switch(cant) {

case 1:
ret = getNumberByIndex(_letters.indexOf(str));
break;

case 2:
chars = str.split("");
ret = ((_letters.indexOf(chars[0]) < _letters.indexOf(chars[1])) ? getNumberByIndex(_letters.indexOf(chars[1])) - getNumberByIndex(_letters.indexOf(chars[0])) : getNumberByIndex(_letters.indexOf(chars[0])) + getNumberByIndex(_letters.indexOf(chars[1])));
break;

case 3:
chars = str.split("");
ret = sumAllNumbers(getNumberByIndex(_letters.indexOf(chars[0])), getNumberByIndex(_letters.indexOf(chars[1])), getNumberByIndex(_letters.indexOf(chars[2])));
break;

case 4:
chars = str.split("");
ret = sumAllNumbers(getNumberByIndex(_letters.indexOf(chars[0])), getNumberByIndex(_letters.indexOf(chars[1])), getNumberByIndex(_letters.indexOf(chars[2])), getNumberByIndex(_letters.indexOf(chars[3])));
break;

}

return ret;

}

//---Retornar un número de acuerdo a su index en el arreglo de letras
protected static function getNumberByIndex(index:uint):uint {
return ((index % 2 == 0) ? Math.pow(10, index / 2) : Math.pow(10, (index + 1) / 2) / 2);
}

//---Función de devolver un string repetido
protected static function repeat(char:String, times:uint):String {
var ret:String = "";
while (times > 0) { ret += char; times--; }
return ret;
}

//---Función de sumar varios números
protected static function sumAllNumbers(...rest):uint {
var all:uint = 0;
var n:uint;
for each(n in rest) { all += n; }
return all;
}

}

}


La clase cuenta con tres métodos estáticos:

testRoman

public static function testRoman(roman:String):Boolean
Comprueba si el valor enviado es un número romano válido

Parámetros

roman:String Valor de tipo cadena con la representación del número romano

Devuelve

Boolean

getRomanNumber

public static function getRomanNumber(number:uint):String
Devuelve un número romano

Parámetros

number:uint Valor positivo entero mayor que 0 con el número que se desea convertir

Devuelve

String Representación del número romano

getArabicNumber

public static function getArabicNumber(roman:String):uint
Devuelve un número arábigo

Parámetros

roman:String Valor de tipo cadena con la representación del número romano

Devuelve

uint Valor entero positivo con la representación numérica del número arábigo

Ejemplos

Código :

import ecn.format.RomanNumbers;

trace(RomanNumbers.testRoman("MMX")); //true
trace(RomanNumbers.testRoman("XMM")); //false
trace(RomanNumbers.getRomanNumber(123456)); //(C)(X)(X)MMMCDLVI
trace(RomanNumbers.getArabicNumber("(D)(C)(L)M(V)CCCXXI")); //654321


Aquí les dejo una pequeña aplicación con la implementación de la clase:


Espero que les sea de ayuda.
Un saludo

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate