• Miércoles 20 de Noviembre de 2024, 05:35

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - marcodigo

Páginas: [1]
1
Fortran / Re: Numeros Romanos Y Arabigos
« en: Martes 22 de Julio de 2008, 00:49 »
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!!!!!!!!!!!!!!!!!!!

Páginas: [1]