miércoles, 16 de febrero de 2011

Convertir números arabigos a números romanos y números romanos a números arabigos

/**
* Conversor.java 
* 1.0
*  
* 12/10/2005 
* 
* Copyright 2005 Lisibeth Troconis. All rights reserved. Used by permission. 
* 
* Libreria para convertir números arabigos a números romanos y números 
* romanos a números arabigos
*/
public class Conversor {
 
 /**
  * SIMBOLO_ROMANO[]: arrreglo que almacena los sinbolos correspondientes al
  * alfabeto perteneciente a los números romanos
  */
 private static final String SIMBOLO_ROMANO[] = 
   { "M", "CM", "D", "CD", "C","XC", "L", "XL", "X", "IX", "V", "IV", "I" };

 /**
  * VALOR_ROMANO_ARABIGO[]: arrreglo que almacena valores arabigos que
  * corresponden a cada símbolo romano
  */
 private static final int VALOR_ROMANO_ARABIGO[] = { 1000, 900, 500, 400,
   100, 90, 50, 40, 10, 9, 5, 4, 1, 0 };

 /**
  * Longitud de los arreglos SIMBOLO_ROMANO[]y VALOR_ROMANO_ARABIGO[]
  */
 private static final int n = 13; 

 
 private static String tomarValorRomano(int cifra) {
  
  if (cifra == 0){
   return "";
  } 
  int i;//indice posición del valor o simbolo romano
  
  /**
   * busco el simbolo que le corresponde
   */
  for (i = 0; i < n; i++){
   if (cifra >= VALOR_ROMANO_ARABIGO[i]){
    break;
   } 
  }
  int v = VALOR_ROMANO_ARABIGO[i];
  String valorRomano = SIMBOLO_ROMANO[i];

  /**
   * Se ve si es un simbolo prohibido y si lo es se busca el siguiente que
   * no lo es
   */
  for (; ((v < cifra) && ((SIMBOLO_ROMANO[i] == "V")
    || (SIMBOLO_ROMANO[i] == "L") || (SIMBOLO_ROMANO[i] == "D") 
    || (SIMBOLO_ROMANO[i].length() > 1))); i++);
  while (v < cifra) {
   v = v + VALOR_ROMANO_ARABIGO[i];
   valorRomano = valorRomano + SIMBOLO_ROMANO[i];
  }
  return valorRomano;
 }

 public static String aRomano(int nArabigo) {
  
  /**
   * Se verifica el rango y si es erroneo retorna vacio
   */
  if (nArabigo > 3999 || nArabigo < 1) {
   return null;
  }

  /**
   * Se convierte el número a Romano
   */
  String resultado = "";// acumulador
  int base = 10; // posicion del número a convertir
  do {
   int cifra = nArabigo % base;
   resultado = tomarValorRomano(cifra) + resultado;
   nArabigo = nArabigo - cifra;
   base = base * 10;
  } while (nArabigo != 0);
  return resultado;
 }

 private static int estadoSiguiente(int edoActual, char caracter) {
  
  /**
   * Se verifica el caracter y se busca su correspondiente indice en el
   * automata Se inicializa a 7 para representar que el caracter es
   * cualquier valor diferente del Alfabeto valido
   */
  int posAlfabeto = 7;
  switch (caracter) {
  case 'I':
   posAlfabeto = 0;
   break;
  case 'V':
   posAlfabeto = 1;
   break;
  case 'X':
   posAlfabeto = 2;
   break;
  case 'L':
   posAlfabeto = 3;
   break;
  case 'C':
   posAlfabeto = 4;
   break;
  case 'D':
   posAlfabeto = 5;
   break;
  case 'M':
   posAlfabeto = 6;
  }
  
  /**
   * sintaxi: Automata de aceptación de la cadena de los números romanos
   * Aceptación>0 y Rechazo = -1, Alfabeto = {I V X L C D M} Estados =
   * 0..19
   */
  int[][] sintaxi = 
               // I   V   X   L   C   D   M, OTRO /*estado*/    
              {{ 1,  4,  5,  8,  9, 12, 14, -1}, /* (0) */
               { 2,  3,  3, -1, -1, -1, -1, -1}, /* (1) */ 
               { 3, -1, -1, -1, -1, -1, -1, -1}, /* (2) */
               {-1, -1, -1, -1, -1, -1, -1, -1}, /* (3) */
               {16, -1, -1, -1, -1, -1, -1, -1}, /* (4) */
               { 1,  4,  6,  7,  7, -1, -1, -1}, /* (5) */ 
               { 1,  4,  7, -1, -1, -1, -1, -1}, /* (6) */  
               { 1,  4, -1, -1, -1, -1, -1, -1}, /* (7) */  
               { 1,  4, 18, -1, -1, -1, -1, -1}, /* (8) */  
               { 1,  4,  5,  8, 10, 11, 19, -1}, /* (9) */  
               { 1,  4,  5,  8, 11, -1, -1, -1}, /* (9) */  
               { 1,  4,  5,  8, -1, -1, -1, -1}, /* (11)*/  
               { 1,  4,  5,  8, 13, -1, -1, -1}, /* (12)*/  
               { 1,  4,  5,  8, 10, -1, -1, -1}, /* (13)*/  
               { 1,  4,  5,  8,  9, 12, 15, -1}, /* (14)*/ 
               { 1,  4,  5,  8,  9, 12, 16, -1}, /* (15)*/  
               { 1,  4,  5,  8,  9, 12, -1, -1}, /* (16)*/  
               { 2, -1, -1, -1, -1, -1, -1, -1}, /* (17)*/  
               { 1,  4,  6, -1, -1, -1, -1, -1}, /* (18)*/ 
               { 1,  4,  5,  8, -1, -1, -1, -1}};/* (19)*/  
 
  /**
   * retorna el estado siguiente en el automata
   */
  return sintaxi[edoActual][posAlfabeto];
 }

 private static boolean validaRomano(String nRomano) {
  int edo = 0; //se inicializa el estado
  
  /**
   * Se recorre el automata y se verifica que es correcta la sintaxi del
   * romano
   */
  for (int i = 0; edo >= 0 && i < nRomano.length(); i++) {
   edo = estadoSiguiente(edo, nRomano.charAt(i));
  }
  
  /**
   * se retorna la condición de aceptación o rechazo
   */
  return ((edo < 0) ? false : true);
 }

 public static int aArabigo(String nRomano) {
  
  /**
   * Se verifica la sintaxi correcta de la cadena que se recive
   */
  if (!validaRomano(nRomano)) {
   return -1;
  }
  int valorArabigo = 0; // acumulador
  int anterior; // indice del simbolo anterior en la cadena
  int actual; // indice del simbolo actual en la cdena
  /**
   * Se toma el valor arbigo actual del final de la cadena que luego sera
   * el valor anterior en la cadena
   */
  for (actual = 0; actual < n; actual++)
   if (SIMBOLO_ROMANO[actual].compareTo(nRomano.charAt(nRomano
     .length() - 1)
     + "") == 0) {
    valorArabigo = VALOR_ROMANO_ARABIGO[actual];
    break;
   }
  anterior = actual;
  
  /**
   * Se convierte el romano a arabigo recorriendo desde el final hacia
   * adelante la cadena, caracer por caracter Sumando su valor si el valor
   * del caracter anterior es mayor o igual al valor del caracter actual y
   * restando si el valor anterior es menor
   */
  for (int i = nRomano.length() - 2, j = 0; i >= 0; i--) {
   for (actual = 0; actual < n; actual++) {
    if (SIMBOLO_ROMANO[actual].compareTo(nRomano.charAt(i) + "") == 0) {
     break;
    }
   }
   if (VALOR_ROMANO_ARABIGO[actual] < VALOR_ROMANO_ARABIGO[anterior]) {
    valorArabigo = valorArabigo - VALOR_ROMANO_ARABIGO[actual];
   } else {
    valorArabigo = valorArabigo + VALOR_ROMANO_ARABIGO[actual];
   }
   anterior = actual;
  }
  return valorArabigo;
 }
}

7 comentarios:

Unknown dijo...

Hola Lisibeth, estaba probando tu libreria conversor.java, pero como le hago para implementarla en el metodo principal.?

Unknown dijo...

Hola lisibeth, estaba probando la liberia de conversor.java, pero como le hago para implementarla en el método principal. Gracias.

Unknown dijo...

Hola Lisibeth, estaba probando tu libreria conversor.java, pero como le hago para implementarla en el metodo principal.?

Lisibeth dijo...

hay dos métodos estáticos en la librería, esos son los que puedes usar

public static int aArabigo(String nRomano)

public static String aRomano(int nArabigo)

Anónimo dijo...

gracias :)

Unknown dijo...

hola lisibeth, estaba probando tu codigo pero me marca error al correrlo, asi aparece en mi pantalla conversor.Conversor class wasn´t found in conversor project.
me podrias decir que es lo que pasa y gracias por el blog.

Unknown dijo...
Este comentario ha sido eliminado por un administrador del blog.