Convert Roman Numbers -> Decimal Numbers  

Send By: Jose Antonio Garcia Navarro
Web : N.A.
Email: enetesystems@wanado.es
Date: 05/05/01

Tip accessed 971 times

 


Starting from the trick [188] I have created a function that makes the opposite, to transform a number in Roman to one into Decimal. Also, I have created a function to validate a number in Roman.


Function for validate a roman number




 function EsRomano(Roman : String) : Boolean;
 const
   Romanos : Array[1..13] of String  =  ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L',
                                         'XL', 'X', 'IX', 'V', 'IV', 'I');
 var
   i  : Integer;
   Ro : String;
   Longitud  : Integer;
   Temporal  : String;
   RomanTemp : String;
   Cantidad  : Integer;
   NumMayor  : Boolean;
   Entrado   : Boolean;
   Sucesion  : Boolean;
 begin
   Result    := False;
   Temporal  := '';
   NumMayor  := True;
   Entrado   := False;
   Sucesion  := True;

   {Se copia el valor del número romano en una variable temporal}
   RomanTemp := Roman;

   {En este bucle se comprueba primero si los DIGITOS están en orden, y
   además se repiten como máximo su número de veces}
   for i := 1 to 13 do
   begin
     Longitud := Length(Romanos[i]); // Longitud del Dígito en Romano. {1 o 2}
     Ro := Copy(RomanTemp, 1, Longitud); // Se coge del Número la cdad. de dígitos como el dígito i.
     Cantidad := 0; // Número de veces que se repite a 0.

     {Se repite este bucle hasta que dígito que cogemos de la Cadena sea igual a digito i}
     while ((Length(RomanTemp)>0) and (Ro = Romanos[i])) do
     begin
       {Se quita el primer dígito de la cadena}
       RomanTemp  := Copy(RomanTemp, 1 + Longitud, Length(RomanTemp) - Longitud);
       {Se llena esta variable temporal}
       Temporal := Temporal + Romanos[i];
       {Se coge el siguiente dígito con la misma cantidad que el dígito i}
       Ro := Copy(RomanTemp, 1, Longitud);
       Inc(Cantidad);
       Entrado := True;
     end;

     if Entrado then
     begin
       case i of
         5, 9, 13 : // C, X y I se pueden repetir 3 veces.
           if Cantidad > 3 then
             NumMayor := False;
         2, 3, 4, 6, 7, 8, 10, 11, 12 : // CM, D, CD, XC, L, XL, IX, V, IV se pueden repetir 1 vez.
           if Cantidad > 1 then
             NumMayor := False;
       end;
       Entrado := False;
     end;
   end;

   {Si Temporal y el número Roman no son iguales es porque Roman no tiene los dígitos en un orden correcto.
    Se entra si el número tiene los dígitos en orden y la cantidad es correcta,
    entonces se comprueba que después de un dígito van los que le corresponden.
    Es decir, después de XC (90) no puede ir L (50)}
   if ((Temporal = Roman) and NumMayor) then
   begin
     RomanTemp := Roman;
     for i := 1 to 13 do
     begin
       Longitud := Length(Romanos[i]);
       Ro := Copy(RomanTemp, 1, Longitud);
       while (Sucesion and (Length(RomanTemp)>0) and (Ro = Romanos[i])) do
       begin
         case i of
           2, 6, 10 : // Si es CM, XC o IX.
           begin
             { Se comprueba que el dígito siguiente no sea el siguiente en la sucesión.
               P. ej. CM -> el siguiente no puede ser D}
             if (Copy(RomanTemp,3,1) = Romanos[i+1]) then
               Sucesion := False
             else
               {Se compureba que el dígito siguiente no sea el de dos posiciones más en la sucesión.
                P. ej. XC -> el siguiente no puede ser CD}
               if (Copy(RomanTemp,3,2) = Romanos[i+2]) then
                 Sucesion := False
               else
                 {Se comprueba que el dígito siguiente no sea el de tres posiciones más en la sucesión.
                  P. ej. IX -> el siguiente no puede ser I}
                 if (Copy(RomanTemp,3,1) = Romanos[i+3]) then
                   Sucesion := False;
           end;
           3, 7, 11 : // Si es D, C o X.
             {Se comprueba que el siguiente no sea CD, XL o IV}
             if (Copy(RomanTemp,2,2) = Romanos[i+1]) then
               Sucesion := False;
           4, 8, 12 : // Si es CD, XL o IV.
             {Se comprueba que el siguiente no sea C, X o I}
             if (Copy(RomanTemp,3,1) = Romanos[i+1]) then
               Sucesion := False
         end;
         RomanTemp := Copy(RomanTemp, 1 + Longitud, Length(RomanTemp) - Longitud);
         Ro := Copy(RomanTemp, 1, Longitud);
       end;
     end;
     Result := Sucesion;
   end
   else
     Result := False;
 end;




Function for convert Roman to Decimal




 function RomanToDec(Roman : String): LongInt;
 const
   Numeros : Array[1..13] of Integer =  (1000, 900, 500, 400, 100, 90, 50, 40,
                                         10,   9,   5,   4,   1);
   Romanos : Array[1..13] of String  =  ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L',
                                         'XL', 'X', 'IX', 'V', 'IV', 'I');
 var
   i : Integer;
   Ro : String;
   Longitud : Integer;
 begin
   Result := 0;

   Roman := UpperCase(Roman);

   if EsRomano(Roman) then
     for i := 1 to 13 do
     begin
       Longitud := Length(Romanos[i]);
       Ro := Copy(Roman, 1, Longitud);
       while ((Length(Roman)>0) and (Ro = Romanos[i])) do
       begin
         Roman  := Copy(Roman, 1 + Longitud, Length(Roman) - 1);
         Result := Result + Numeros[i];
         Ro := Copy(Roman, 1, Longitud);
       end;
     end;
 end;