hola, sé que la ayuda llega tarde, pues recién hoy (21/07/08) me enteré de la existencia de este website. en fin, tengo un código en fortran, que le podría servir de "inspiración" a alguien en el futuro. el código que a continuación verán lo hice muy pedagógico a fin de hacer fácil su entedimiento (este algotimo puede ser mucho más eficiente), está hecho en fortran.
program romano_arabico
integer,dimension(5)::probador=(/1243,53,16,1536,3999/)
character (len=12)::romano
character (len=12),dimension(5)::char
integer::i,arabico
!Aquí probamos el correcto funcionamiento de la conversión de un número arábico a un número romano
print*,"de arabico a romano"
do i=1,5
call arabico_a_romano(probador(i),romano)
print*,"arabico",probador(i)," ------ ","romano:",romano
romano=' '
end do
!Aquí probamos la conversión de número romano a arábico, en este caso es recomendable saber que la subrutina romano_arabico no hace chequeo de error
!de los datos introducidos (número romano), por lo tanto el usuario se debe encaragar de verificar de que está introduciendo un número romano
char(1)='MMDVII'
char(2)='III'
char(3)='L'
char(4)='IV'
char(5)='MMMCMXCIX'
do i=1,5
call romano_a_arabico(char(i),arabico)!chequear salidas y el uso correcto de las subrutinas
print*,"romano:",char(i)," ------ ","arabico:",arabico
end do
contains
subroutine arabico_a_romano(arabico,romanova)
!máximo número representable: 3999
integer::arabico
real, dimension(7):: valarabico=(/1,5,10,50,100,500,1000/)
character,dimension(7):: valaromano= (/"I","V","X","L","C","D","M"/)
character,dimension(12):: romano,romanova
character::roma,roma2
real,allocatable,dimension(
:: cifra_decimal,cifras_valederas
integer::contador,i,j,k,v,w,contador2,cota,a,b
real::arabicop,arabico2,arabico3,arabico4,valorabico,valorabico2,valorabico3,valorabico4,arabico5,arabico6,valorabico5
arabico5=arabico
cota=7
valorabico=0
contador=0
arabicop=arabico
!el primer paso que daremos es separar el número en cifras de base diez, por lo tanto el primer debemos primeramente guardar espacio para el
!vector que contendrá esas cifras
do while (arabicop>=1)
arabicop=arabicop/10
contador=contador+1
end do
allocate(cifra_decimal(contador),cifras_valederas(contador))
arabicop=arabico
arabicop=int(arabicop)
do i=1,contador!En este ciclo hacemos la separación en cifras de base diez
arabicop=arabicop/10!dividimos el número en cuestión por diez
arabico3=arabicop-int(arabicop)!calculamos la diferencia entre el número original y su diferencia
arabico4=arabico3*(10**i)!sabiendo cuantos dígitos debe tener el número, lo multiplicamos por 10 a la número de dígitos
arabico2=floor(arabico4)+1!hay casos particulares en los que el número obtenido no es un entero, para evadir este problema hallamos el piso del
arabico6=arabico5!número y sumamos uno
arabico5=arabico5-arabico2!y ese número es restado con el número arábico original a manera de reportar el cambio
if (mod(arabico5,5.0)/=0)then!si el número obtenido no es divisible por cinco,debemos calcular la diferencia del error y corregirlo
arabico2=arabico2-1
arabico5=arabico6-arabico2
end if
cifra_decimal(i)=arabico2!guaradamos la cifra en base diez
arabicop=int(arabicop)!eliminamos los decimales ya usados
end do
contador2=1
do i=contador,1,-1!vemos si hay elemenros del vector cifra_decimal que sean cero, estos los eliminamos
arabico2=cifra_decimal(i)
if (arabico2/=0)then
cifras_valederas(contador2)=arabico2
contador2=contador2+1
end if
end do
j=1
arabico6=arabico
do i=1,contador2-1
valorabico=0
arabico2=cifras_valederas(i)
contador=1
if (arabico2<1000)then!en este ciclo lo que se intenta es determinar en que intervalo está el arábico en cuestión, es principalmente hallar la representación
do while (valorabico<=arabico2.and.contador<=cota)!en número romanos de un dígito que más se aproxime inferiormente a el arábico original
valorabico=valarabico(contador)!sabemos que si el número es mayor o igual a mil, la representación es M, aquí estudiamos los demás casos
contador=contador+1
end do
else
contador=9!aquí aseguramos que si el arábio es mayor o igual a mil la representación sea M
end if
roma=valaromano(contador-2)!hallamos la representación de un sólo dígito romano del número en cuestión
valorabico=valarabico(contador-2)!y el número que corresponde a ese caracter
if (contador>3)then!sabemos que si el número tiene tiene más de una cifra puede escribirse empleando números de menor valía antes de números de
roma2=valaromano(contador-3)!mayor valor, por ejemplo 9=IX
valorabico2=arabico6-arabico2
arabico5=valorabico2/valarabico(contador-3)
arabico6=aribico6-arabico2
end if
arabico4=arabico2/valorabico
valorabico2=arabico2-valorabico
arabico5=valorabico2/valarabico(contador-3)
if (valorabico==arabico2)then!caso en el que el número arabico requiere de un solo número romano para su representación
romano(j)=roma
j=j+1
elseif(arabico4==int(arabico4).and.arabico4<=3)then!Caso en el que el número sólo requiere de un número romnano para su representación, aunque ene este
k=arabico4!caso el número puede repetirse, específicamente hasta un máximo de tres ocasiones.
do v=j,j+k-1
romano(v)=roma
end do
j=v+1
elseif ((contador>3.and.(arabico5==int(arabico5))).and.(int(arabico5)<=3))then!Caso en el que el número se representa como la unión de dos tipos de números
w=valorabico2/valarabico(contador-3)!que se ubicarán de orden de mayor a menor, ejemplo 8=VIII
romano(j)=roma
j=j+1
do v=j,j+w-1
romano(v)=roma2
end do
j=v+1
else!Caso en el que el número se representa como la unión de dos números de distinto valor, y que en la representación se ordenan de menor a mayor
valorabico3=valarabico(contador-1)-arabico2
valorabico5=contador-1
if (mod(valorabico5,2.0)==0)then
valorabico4=contador-2
else
valorabico4=contador-3
end if
w=int(valorabico3/valarabico(int(valorabico4)))
a=j
roma2=valaromano(int(valorabico4))
do v=j,j+w-1
romano(v)=roma2
end do
j=v
romano(j)=valaromano(contador-1)
end if
end do
do i=1,j-1
romanova(i)=romano(i)!creamos el vector solución
end do
end subroutine arabico_a_romano
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11
subroutine romano_a_arabico(romano,arabico)
integer:: arabico
integer::fratore
real, dimension(7):: valarabico=(/1,5,10,50,100,500,1000/)
character,dimension(7):: valaromano= (/"I","V","X","L","C","D","M"/)
INTEGER,ALLOCATable,DIMENSION(
::romanosval,romanosindval,cantidad,romanosindar
CHARACTER (LEN=12)::romano,romano2
character::roma,roma2,roma3
real,allocatable,dimension(
:: cifra_decimal,cifras_valederas
integer::contador,i,j,k,v,w,contador2,cota,a,b,suma1,suma2,suma3,recargo
real::arabicop,arabico2,arabico3,arabico4,valorabico,valorabico2,valorabico3,valorabico4,arabico5,arabico6,valorabico5
!conversión de romano a arábico
cota=len_trim(ROMANO)!calculamos la cantidad de caracteres empleados en la representación en números romanos para acotar el vector
contador=3
if (cota<3)then
contador=cota
end if
allocate (romanosval(cota),romanosindval(cota),cantidad(cota),romanosindar(cota))
j=1
do i=1,cota!separamos uno uno los números romanos que en su unión forman al número romano original, lo hago de esta manera para verificar que
roma2=romano(i:i)!cual es el número correspondiente
do j=1,7
roma3=valaromano(j)
if(roma3==roma2)then
romanosval(i)=valarabico(j)
end if
end do
end do
i=1
k=1
do while (i<=cota)!A continuación organizo apropiadamente la representación arábica de los números romanos en cuestión,y cuento
contador=romanosval(i)!cuantos elementos de un mismo tipo se encuentran en una cadena continua, si no forman cadena simplemente hay un elemento
contador2=contador!en la representación
j=1
do while (contador==contador2)
contador2=romanosval(i+j-1)
j=j+1
end do
i=i+j-2
cantidad(k)=j-2
romanosindval(k)=contador
k=k+1
end do
do i=1,cota-1
if (romanosindval(i)<romanosindval(i+1))then!tomo cada una de las representaciones arábicas (aquí no tomaré el último dígito),veo su vecino
romanosindar(i)=-(romanosindval(i))!más próximo a la derecha y si soy menor que él, entonces soy negativo
else
romanosindar(i)=romanosindval(i)
end if
end do
romanosindar(cota)=romanosindval(cota)!el último siempre es positivo
suma1=0
do i=1,cota!ahora sólo sumo, sabiendo la longitud de sus cadenas continuas formadas
suma1=suma1+(cantidad(i)*romanosindar(i))
end do
arabico=suma1
end subroutine romano_a_arabico
end program romano_arabico
cualquier duda, aquí dejo mi correo:
m06-39306usbmat@hotmail.com.
suerte!!!!!!!!!!!!!!!!!!!