Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Caster en 11 Mayo 2014, 15:04 pm



Título: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 11 Mayo 2014, 15:04 pm
Buenas a todos, estoy intentando hacer un programa que pase de números arábigos a romanos, busqué en el foro pero solo encontré un par de temas en los que se hablaba de como hacer el proceso a la inversa. Lo que yo había pensado era darle a programa las equivalencias entre los numeros romanos y los arábigos e ir comparando, me explico:
-Si tenemos el numero 200, el numero romano mas grande que podemos utilizar para representar el 200 es C, entonces se escribe una C y se resta a 200, quedarían otros 100 y por lo tanto se pondría otra C, 200= CC.
-Lo mismo por ejemplo con el número 1200, el romano mas cercano al 1200 y que no sea mayor es M, se restaria a 1200 quedando 200, y a partir de aqui igual que el proceso para el número anterior.

El problema viene si se trata del número 4 por ejemplo, V no valdría porque es mayor entonces, siguiendo el mismo proceso de antes, seria IIII, pero eso tampoco es posible, quería alguna orientación para saber como resolver este problema o hacia donde orientar mi programa, muchas gracias.

Un saludo.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: ivancea96 en 11 Mayo 2014, 15:37 pm
Pues podrías poner unas condiciones. Por ejemplo:

124:
Si está entre 100 <= n < 400 : C -> Restamos 100
24:
Si está entre 10 <= n < 40 : X -> Restamos 10
14:
(...) : X -> Restamos 10
4:
Si está entre 4 <= n < 5 //(n = 4)// : IV -> Restamos 4

Al final, se reduciría a 4 condiciones en cada cifra:
Código:
1*10^X <= n < 4*10^X
4*10^X <= n < 5*10^X
5*10^X <= n < 9*10^X
9*10^X <= n < 10*10^X

Es un método un poco bruto por tanto condicional, pero ahora no se me ocurre otro xD


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 11 Mayo 2014, 16:24 pm
No lo entendí muy bien

Al final, se reduciría a 4 condiciones en cada cifra:
1*10^X <= n < 4*10^X
4*10^X <= n < 5*10^X
5*10^X <= n < 9*10^X
9*10^X <= n < 10*10^X

¿Qué son esas X?

Haciéndolo con el 379 por ejemplo:

379:
Si está entre 100 <= n < 500: C -> restamos 100
279:
Si está entre 100 <= n < 500: C -> restamos 100
179:
Si está entre 100 <= n < 500: C -> restamos 100
79:
Si está entre 50 <= n < 100: L -> restamos 50
29:
Si está entre 10 <= n < 50: X -> restamos 10
19:
Si está entre 10 <= n < 50: X -> restamos 10

Quedan 9, siguiendo el mismo proceso primero se restaría 5(V) y despues 4(IIII) y quedaría por lo tanto CCCLXXVIIII pero el correcto sería CCCLXXIX, creo que no era algo así lo que dices tu, pero no lo entendí.

Un saludo


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: ivancea96 en 11 Mayo 2014, 16:39 pm
Para esos 9 sería:
9*10^X <= n < 10*10^X

Perdón, se me olvidó ponerlo: X sería la cifra. En fin, ignóralo.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: erest0r en 11 Mayo 2014, 20:23 pm
Fijate que las unidades, las decenas, centenas, etc, en los numeros romanos siguen un mismo patron

*De 1 a 3 se repite esa cantidad de veces el simbolo = I, II, III; X, XX, XXX, etc

*Al 4 se le resta la unidad al numero del medio = IV; XL; CD

*Luego el numero del medio = V, L, D

*Despues del 6 al 8 va el numero central mas las unidades correspondientes = VI, VII, VIII; LX, LXX, LXXX

* Al penultimo numero se le resta la unidad al siguiente aumento de digito = IX, XC, CM

* Por ultimo, el numero de digito adicional = X, C, M

Puedes crear una matriz que en cada fila almacene los caracteres dependiendo de la cantidad de digitos y puedes resolver.

Código
  1. char letras[4][3] = { 'I', 'V', 'X',
  2.                      'X', 'L', 'C',
  3.                      'C', 'D', 'M',
  4.                      'M'};
  5.  


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 12 Mayo 2014, 23:25 pm
Para esos 9 sería:
9*10^X <= n < 10*10^X

Perdón, se me olvidó ponerlo: X sería la cifra. En fin, ignóralo.

Vas a tener que perdonar mi torpeza pero no terminé de entenderlo, ¿la cifra? Entonces si la cifra es 234 sería 9x10^234, eso es un número enorme. Y después, esa sería la condición, ¿pero que tendría que hacer en ese caso?

erest0r, no entendí muy bien el patrón que siguen, a partir del número 4 me perdi.

Muchas gracias, un saludo.


Título: Re:
Publicado por: ivancea96 en 13 Mayo 2014, 00:06 am
Con cifra me refería al número de cifras del num. Pero olvídalo, creo que el método de erest0r te podría servir mejor.

Enviado desde mi ST21i mediante Tapatalk


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: erest0r en 13 Mayo 2014, 01:59 am
Empiezas a extraer cada digito del numero ingresado, y lo asocias a cual fila pertenece:

2014: 4 por ser unidad lo evaluas en la primera fila, 1 por ser decena lo evaluas en la segunda fila , etc. Todo eso en caso que lo hagas con la matriz que te mostre.

Luego con un switch haces el procedimiento de evaluacion.

Código
  1. switch( numero )
  2.    {
  3.        case 1:
  4.        case 2:
  5.        case 3:
  6.            for( i = 0; i < numero; i++ )
  7.                digito_romano[i] = letras[cant_decimal][0];
  8.        break;
  9.        case 4:
  10.            for( i = 0; i < 2; i++ )
  11.                digito_romano[i] = letras[cant_decimal][i];
  12.        break;
  13.        case 5:
  14.            digito_romano[0] = letras[cant_decimal][1];
  15.            i++;
  16.        break;
  17.        case 6:
  18.        case 7:
  19.        case 8:
  20.            digito_romano[0] = letras[cant_decimal][1];
  21.            for( i = 1; i <= numero - 5; i++ )
  22.                digito_romano[i] = letras[cant_decimal][0];
  23.        break;
  24.        case 9:
  25.            digito_romano[0] = letras[cant_decimal][0];
  26.            digito_romano[1] = letras[cant_decimal][2];
  27.            i = 2;
  28.        break;
  29.    }
  30.    digito_romano[i] = '\0';
  31.  

A cada digito le harias ese proceso, fijate que la variable "cant_decimal", te indica si el digito es unidad, decena, centena, una vez guardado en "digito_romano", lo concatenas con el "digito_romano" equivalente de los demas digitos, y ya esta.



Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 13 Mayo 2014, 22:03 pm
Ya he empezado a peleame con el código por la parte de separar los digitos de los numeros, esto lo llevo bien, lo que no termino de entender es el patrón que siguen los numeros romanos, el primer punto creo que lo entiendo, cuando en las unidades o decenas o centenas... aparece el numero 3, se repiten 3 veces, por ejemplo, 376, en las centenas a parece el numero 3 por lo tanto en romanos el numero empezara por CCC... lo que si que no entiendo son el resto de puntos a partir de este.

Un saludos


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: erest0r en 13 Mayo 2014, 22:25 pm
Amigo asi mismo como tu dices, tienes 376 va a formar parte de la centena para lo cual le tocaria la fila[2], luego el 7 por ser decena le toca la fila[1] y el 6 le toca la fila[0] por ser unidad, solo necesitas un contador que te lleve la cuenta con cual fila vas a trabajar dependiendo del digito. Extraes el 3 lo evaluas y tienes CCC, ahora te deberia quedar 76, extraes el 7 y te da LXX, te queda ya solamentre el 6 por evaluar que le corresponderia VI.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 13 Mayo 2014, 22:39 pm
No me estas entendiendo lo que te quiero decir, lo que no es el patrón que siguen los numeros, no entiendo a que te refieres más arriba cuando me lo explicas con  "se le resta la unidad al numero del medio"



Y aprovecho ya, porque pense que lo de separar los digitos de los numeros me iba bien pero ya me esta dando problemas, tenog este codigo:
Código
  1. #include <stdio.h>
  2. #include <math.h>
  3.  
  4. int main()
  5. {
  6. int num, i;
  7. int digitos[2];
  8. printf("Introduzca el numero (maximo 3 digitos):\n");
  9. scanf("%d", &num);
  10.  
  11. for (i = 2; i >= 0; i--)
  12. {
  13. digitos[i] = num / (pow(10, i));
  14. num -= digitos[i] * (pow(10, i));
  15. }
  16.  
  17. printf("%d\n", digitos[0]);
  18. printf("%d\n", digitos[1]);
  19. printf("%d\n", digitos[2]);
  20. return 0;
  21. }

Los printf son simplemente para ver si da el resultado esperado, la salida de este programa es (introduciendo 123):

Citar
-9
-9
0

Cuando la salida esperada sería:
Citar
3
2
1

Sin embargo si el array digitos lo declaro como digitos[3] el programa arroja el resultado esperado y no entiendo donde radica la diferencia.

Un saludo.

EDITO:Ya entendi el funcionamiento del algoritmo, solo me queda saber el error que me da al separar el numero en digitos, muchas gracias.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: ivancea96 en 13 Mayo 2014, 22:45 pm
"int digitos[2];"
Estás diciendo que el array tiene 2 casilles (0 y 1). No debes acceder a digitos[2].


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 13 Mayo 2014, 22:50 pm
"int digitos[2];"
Estás diciendo que el array tiene 2 casilles (0 y 1). No debes acceder a digitos[2].

Estaba haciéndolo desde el punto de vista de que digitos[2] significaba que existia digitos[0], digitos[1] y digitos[3], muchas gracias.

Un saludo


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: erest0r en 13 Mayo 2014, 23:35 pm
Tienes un contador inicializado en 0, y se introduce ejemplo el 376, entonces extraes el 6 en una variable y lo evaluas en el switch, la variable donde dice "cant_decimal" es donde va tu contador, en ese primer caso seria 0, y es correcto porque 6 pertenece a las unidades, y lo guardas en un vector de caracteres, luego haces lo mismo con el 7, en ese caso aumenta tu contador, y evaluas a 7 en la segunda fila que son las decenas otra vez con el switch y lo vas almacenando tambien en el vector de caracteres, y asi sucesivamente.

NOTA: Debes estar pendiente cuando guardes en el vector porque los numeros se almacenaran de atras para adelante.

376 = CCCLXXVI, si lo guardas a lo loco en el vector te saldra VILXXCCC.

No se si me he explicado bien.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 17 Mayo 2014, 00:34 am
Buenas, aqui estoy de nuevo, me da mucha rabia postear porque estais haciendo eel trabajo vosotros y no yo, pero es que no logro ver los fallos, supongo que sera por la falta enorme de practica que tengo. El programa, teóricamente, está terminado pero no se porque motivo no da el resultado esperado, aqui el codigo:
Código
  1. #include <stdio.h>
  2. #include <math.h>
  3.  
  4. int main()
  5. {
  6. int num, i, j, cant_decimal = 0, z;
  7. int digitos[3];
  8. char letras[4][3] = { 'I', 'V', 'X'
  9.                                              'X', 'L', 'C',
  10.                                              'C', 'D', 'M',
  11.                                              'M'};
  12. char digito_romano[20];
  13. printf("Introduzca el numero (máximo 3 digitos):\n");
  14. scanf("%d", &num);
  15.  
  16. for (i = 2; i >= 0; i--)
  17. {
  18. digitos[i] = num / (pow(10, i));
  19. num -= digitos[i] * (pow(10, i));
  20. }
  21.    printf("%d\n", digitos[0]);
  22.    printf("%d\n", digitos[1]);
  23.    printf("%d\n", digitos[2]);
  24.  
  25. for(j = 0; j <= 3; j++)
  26. {
  27. switch(digitos[j])
  28. {
  29. case 1:
  30. case 2:
  31. case 3:
  32. for( i = 0; i < digitos[j]; i++ )
  33. digito_romano[i] = letras[cant_decimal][0];
  34. break;
  35.  
  36. case 4:
  37. for( i = 0; i < 2; i++ )
  38. digito_romano[i] = letras[cant_decimal][i];
  39. break;
  40.  
  41. case 5:
  42. digito_romano[0] = letras[cant_decimal][1];
  43. i++;
  44. break;
  45.  
  46. case 6:
  47. case 7:
  48. case 8:
  49. digito_romano[0] = letras[cant_decimal][1];
  50. for( i = 1; i <= digitos[j] - 5; i++ )
  51. digito_romano[i] = letras[cant_decimal][0];
  52. break;
  53.  
  54. case 9:
  55. digito_romano[0] = letras[cant_decimal][0];
  56. digito_romano[1] = letras[cant_decimal][2];
  57. i = 2;
  58. break;
  59. }
  60.  
  61. digito_romano[i] = '\0';
  62. cant_decimal++;
  63. }
  64. for(z=0; z <= 20; z++)
  65. printf("%c", digito_romano[z]);
  66.  
  67. return 0;
  68. }

Probe con algunos numeros y haciendolo mentalmente con el codigo delante aparentemente funciona bien pero seguro que hay algun detalle que se me escapa porque sino tendria que funcionar bien el programa y de verdad que no doy visto donde esta el fallo, porque apostaria a que es una tonteria.

Un saludo

EDITO:Revisando el codigo me fije en que el fallo puede estar en los for's dentro del switch ya que puede ser problema de que la variable i que se utiliza en esos ciclos se ponga a 0 cada ez que se cmabia de cifra entonces eso de problemas, no se.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: erest0r en 17 Mayo 2014, 01:22 am
Amigo el error esta en que el codigo que te sugeri esta pensado para estar en una funcion, y "digito_romano" practicamente seria un arreglo donde se almacena cada digito que despues se pasaria a un arreglo que es donde estarian todos los numeros transformados, es decir, ejemplo:

Código
  1. void funcion( char romano[] )
  2. {
  3.    char digito_romano[4] = { 'I', 'I', 'I', '\0' };
  4.    strcat(romano, digito_romano);
  5. }
  6.  

Porque como podras ver, cada vez que se ejecutaba el switch, todos los datos se volvian a escribir desde el principio en "digito_romano".

Ahora por la forma en que lo tienes, puedes usar una variable contadora que te lleve la posicion actual de cada casilla de tu arreglo digito_romano, asi donde iria digito_romano[ i ] o digito_romano[0], seria algo del tipo digito_romano[pos_digito++]. Y probablemente algunas instrucciones que estan alli quizas ya no sean necesarias.

Como te dije anteriormente en una nota, el resultado de los numeros romanos te va a salir de atras para adelante, eso lo acomodaras. Otra cosa inicializa tu arreglo "digito_romano" por eso es que arroja esos valores basuras y tu for(j) va hasta <= 2 no <= 3.



Saludo.


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 18 Mayo 2014, 16:39 pm
Ya tengo el código y creo que funciona bien, solo me queda saber como hacer para que desaparezcan esos caracteres basura que aparecen en el array, lei sobre la funcion memsert y lo hice asi:

Código
  1. memset(digito_romano, 0, 4);

Pero no consigo hacer que desaparezcan esos caracteres basura.

Un saludo


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Blaster en 18 Mayo 2014, 16:55 pm
Ya tengo el código y creo que funciona bien, solo me queda saber como hacer para que desaparezcan esos caracteres basura que aparecen en el array, lei sobre la

Solo debes inicializarlo de esta manera

Código
  1. char digito_romano[20] = "";

Saludos


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 18 Mayo 2014, 17:52 pm
Bueno, después de romperme mucho la cabeza con este programa, creo que ya está listo, aquí el código para quien le interese:

Código
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4.  
  5. void arabigos_a_romanos(int digitos[]);
  6.  
  7. int main()
  8. {
  9. int i, num;
  10. int digitos[3];
  11.  
  12. puts("Introduzca el numero (maximo 3 digitos):");
  13. scanf("%d", &num);
  14.  
  15. for (i = 2; i >= 0; i--)
  16. {
  17. digitos[i] = num / (pow(10, i));
  18. num -= digitos[i] * (pow(10, i));
  19. }
  20.  
  21. arabigos_a_romanos(digitos);
  22.    return 0;
  23. }
  24.  
  25. void arabigos_a_romanos(int digitos[]){
  26. char x[20], temp;
  27. char digito_romano[4] = "", romano[20] = "";
  28.    char letras[4][3] = { 'I', 'V', 'X',
  29.  'X', 'L', 'C',
  30.  'C', 'D', 'M',
  31.  'M'};
  32. int j, i, cant_decimal = 0, z, y, a;
  33. for(j = 0; j <= 2; j++)
  34. {
  35. switch(digitos[j])
  36. {
  37.            case 0:
  38.                digito_romano[j] = "";
  39. case 1:
  40. case 2:
  41. case 3:
  42. for( i = 0; i < digitos[j]; i++ )
  43. digito_romano[i] = letras[cant_decimal][0];
  44. break;
  45.  
  46. case 4:
  47. for( i = 0; i < 2; i++ )
  48. digito_romano[i] = letras[cant_decimal][i];
  49. break;
  50.  
  51. case 5:
  52.                                i = 0;
  53. digito_romano[0] = letras[cant_decimal][1];
  54. i++;
  55.                break;
  56.  
  57. case 6:
  58. case 7:
  59. case 8:
  60. digito_romano[0] = letras[cant_decimal][1];
  61. for( i = 1; i <= digitos[j] - 5; i++ )
  62. digito_romano[i] = letras[cant_decimal][0];
  63. break;
  64.  
  65. case 9:
  66. digito_romano[0] = letras[cant_decimal][0];
  67. digito_romano[1] = letras[cant_decimal][2];
  68. i = 2;
  69.                break;
  70. }
  71.  
  72. digito_romano[i] = '\0';
  73. cant_decimal++;
  74. strrev(digito_romano);
  75.    strcat(romano, digito_romano);
  76.    }
  77. puts("El numero en romano es:");
  78. for(z=10; z >= 0; z--)
  79.        printf("%c", romano[z]);
  80. }
  81.  

He añadido un case mas al switch porque cuando el numero terminaba en 0 daba un error, pero creo que ahora ya funciona perfectamente. He probado con numeros como 123(CXXIII), 400(CD), 434(CDXXXIV), 200(CC)... y el resultado ha sido siempre el esperado asi que supongo que dare por terminado el programa, muchas gracias a todos los que me habeis ayudado.

Un saludo


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Blaster en 18 Mayo 2014, 18:15 pm
La variable i la debes inicializar a cero, si le pasas al programa un cinco el programa revienta por que en ese ambito el valor i es deconocido, contiene basura y al utilizarlo como indice sobrescribis otras direcciones de memoria

Saludos


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Caster en 18 Mayo 2014, 18:25 pm
La variable i la debes inicializar a cero, si le pasas al programa un cinco el programa revienta por que en ese ambito el valor i es deconocido, contiene basura y al utilizarlo como indice sobrescribis otras direcciones de memoria

Saludos

Tienes razón, problema solucionado. Ya edito el codigo en el post anterior.
Y ya aprovecho para preguntar una cosa, ¿es mejor inicializar siempre las variables para que no se llenen de basura y que den resultados inesperados?

Un saludo


Título: Re: Pasar numeros enteros arábigos a romanos, por donde empezar.
Publicado por: Blaster en 18 Mayo 2014, 18:38 pm
Y ya aprovecho para preguntar una cosa, ¿es mejor inicializar siempre las variables para que no se llenen de basura y que den resultados inesperados?

Si, siempre debes inicializarlas te cuento por que el espacio de memoria "reservado" para tu variable pudo haber sido usado previamente por otro programa o aplicación, la cual libera ese espacio de memoria para el uso de otros programas, pero no necesariamente "borra" el contenido del mismo. Ese contenido no borrado en esa memoria liberada es lo que se llama "basura".

Por lo que una variable sin inicializar puede contener un valor arbitrario que puede generarte un resultado inesperado. Por eso es que se le asigna siempre un valor inicial, para que los resultados sean predecibles.

Saludos