Ver Mensaje Individual
  #107 (permalink)  
Antiguo 11/12/2014, 13:00
kutcher
 
Fecha de Ingreso: noviembre-2014
Mensajes: 36
Antigüedad: 10 años, 1 mes
Puntos: 13
Respuesta: Petando la pila. Problemas y retos usando recursividad.

Cita:
Iniciado por leosansan Ver Mensaje
¡¡¡ Duda, duda ¡¡¡. ¿Y cúal es la duda?. Sencillo el valor que se obtiene supera los límites del tipo "int" y como los resultados obtenidos con el código son correctos me lleva a plantearme dos posibilidades:

** El programa trunca el valor, pero al hacerlo tanto en la cifra del número como en la del factor donde aparece dicho dígito, se compensan los errores.

** El programa al encontrarse un valor tan alto pasa a tomarlo como float, manteniendo todas sus cifras, y tampoco se produce error.
Excelente observación leosansan y ahora paso a explicar porque funciona,
como pueden notar nos encontramos ante un comportamiento indefinido en el lenguaje C en este caso con respecto al operador de desplazamiento a la izquierda:

"El resultado es indefinido si el operando de la derecha es negativo, o mayor o igual que el número de bits en el tipo de la expresión izquierda."

Como sabemos al desplazar:

Código C++:
Ver original
  1. 1 << 54

Se espera como resultado el cero, debido a que los bits que salen por la izquierda se pierden, los que entran por la derecha se rellenan con ceros pero en la expresión que utilizo eso no sucede ocurre una especie de rotación aquí dejo una pagina que explica porque pasa eso en los procesadores Intel arquitectura x86:

http://choorucode.com/2004/12/20/c-shift-operator-mayhem/

Ocurre el siguiente desplazamiento con el ejemplo de leosansan el numero 39:
Código C++:
Ver original
  1. 1 << (39 % 10) * 6 = 1 << 9 * 6 = 1 << 54 = 4194304
Código C++:
Ver original
  1. 00000000 01000000 00000000 00000000
Y en vista de todo esto expongo otra opción pero utilizando otro método para identificar los dígitos, como van a ver hago uso del producto de los números primos:

Código C++:
Ver original
  1. #define MAX(a,b) ((a)>(b)?(a):(b))
  2. #define MIN(a,b) ((a)<(b)?(a):(b))
  3.  
  4. int dec[] = { 1, 10, 100, 1000, 10000, 100000 };
  5. int primos[10] = {2, 3, 5, 7, 11, 13, 17, 23, 29, 31};
  6.  
  7. int fact(int num, int t)
  8. {
  9.     if (!num) return t;
  10.     t *= primos[num % 10];
  11.     return fact(num/10, t);
  12. }
  13. int comprobar(int min, int max, int num, int b, int t)
  14. {
  15.     if(min >= max) return 0;
  16.  
  17.     b = num / min;
  18.     if (min * b == num && ((min % 10) || (b%10))
  19.         && t == fact(min,1) * fact(b,1) )
  20.         return 1;
  21.  
  22.     return comprobar(min + 1, max, num, b, t);
  23. }
  24. int esVampiro(int num)
  25. {
  26.     int min, max, b = 0, nd = log10(num)+1, t = fact(num, 1);
  27.  
  28.     if (nd % 2) return 0;
  29.     nd /= 2;
  30.     min = MAX(dec[nd - 1], (num + dec[nd] - 2)/(dec[nd] - 1));
  31.     max = MIN(num/min, sqrt(num));
  32.  
  33.     return comprobar(min, max, num, b, t);
  34. }

Un saludo

Última edición por kutcher; 11/12/2014 a las 13:09