elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Sucesion de Fibonacci recursiva optimizada
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Sucesion de Fibonacci recursiva optimizada  (Leído 12,416 veces)
do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Sucesion de Fibonacci recursiva optimizada
« en: 20 Julio 2013, 14:11 pm »

¡Buenas!

Esta mañana me he dedicado a perder el tiempo, así que comparto el tiempo perdido con vosotros y no tengo la sensación de haberlo perdido para nada.

Se trata de la sucesión de Fibonacci (ya conocida por todos (supongo)).

El algoritmo obtenido no es tan rápido como la versión iterativa (creo que anda cerca), pero mejora con creces la versión recursiva.

Evidentemente no es inmediata, como la formula que obtiene el enésimo termino en función de n y de phi (el numero aureo...)

Tampoco he utilizado programación dinamica, así que el único problema de memoria, si lo hubiese, estaría originado por una cantidad excesiva de llamadas recursivas.

Aquí os dejo un par de códigos. El primero con explicaciones sobre como se llega a la formula utilizada y con una comparación entre el algoritmo clásico y el optimizado, y el segundo para utilizarlo desde la linea de comandos, por si a alguien le hace ilusión.

¡Saludos!

Código
  1. /*
  2.   JUGANDO UN POCO CON LA SUCESION DE FIBONACCI
  3.   ============================================
  4.  
  5.   La sucesion de Fibonacci se define de forma recursiva como:
  6.  
  7. fibo(n) = n  si n = 0 ó 1
  8. fibo(n) = fibo(n - 1) + fibo(n - 2) si n > 1
  9.  
  10.   Aplicar la recursion de esta forma hace que el numero de llamadas sea de orden
  11. exponencial con respecto al tamaño inicial del dato, por lo que el algoritmo se
  12. vuelve lento rapidamente.
  13.  
  14.   Suponiendo n suficientemente grande podemos descomponer fibo(n - 1) en el paso
  15. de recurcion como sigue:
  16.  
  17. fibo(n) = fibo(n - 1) + fibo(n - 2) = (fibo(n - 2) + fibo(n - 3)) + fibo(n - 2) =
  18. = 2 * fibo(n - 2) + fibo(n - 3)
  19.  
  20.   Aplicamos el mismo proceso a fibo(n - 2):
  21.  
  22. fibo(n) = 2 * fibo(n - 2) + fibo(n - 3) = 2 * (fibo(n - 3) + fibo(n - 4)) + fibo(n - 3) =
  23. = 3 * fibo(n - 3) + 2 * fibo(n - 4)
  24.  
  25.   Y para ver las cosas mas claras lo repetimos con fibo(n - 3):
  26.  
  27. fibo(n) = 3 * fibo(n - 3) + 2 * fibo(n - 4) = 3 * (fibo(n - 4) + fibo(n - 5) + 2 * fibo(n - 4) =
  28. = 5 * fibo(n - 4) + 3 * fibo(n - 5)
  29.  
  30.   Por si no queda claro donde queremos llegar resumimos lo que tenemos hasta ahora:
  31.  
  32.   Cada una de las siguientes expresion son iguales a fibo(n):
  33.  
  34. 1 * fibo(n - 1) + 1 * fibo(n - 2) = fibo(2) * fibo(n - 1) + fibo(1) * fibo(n - 2) =
  35. 2 * fibo(n - 2) + 1 * fibo(n - 3) = fibo(3) * fibo(n - 2) + fibo(2) * fibo(n - 3) =
  36. 3 * fibo(n - 3) + 2 * fibo(n - 4) = fibo(4) * fibo(n - 3) + fibo(3) * fibo(n - 4) =
  37. 5 * fibo(n - 4) + 3 * fibo(n - 5) = fibo(5) * fibo(n - 4) + fibo(4) * fibo(n - 5)
  38.  
  39.   Si seguimos de esta forma podemos intuir que
  40.  
  41.   fibo(n) = fibo(k + 1) * fibo(n - k) + fibo(k) * fibo(n - k - 1) := F(n,k) para 0 <= k < n
  42.  
  43.   Se puede demostrar por induccion que fijando un N natural (N >= 2) se tiene que
  44.  
  45.   fibo(N) = F(N,k) para todo 0 <= k < N
  46.  
  47.   y que fijado K natural para todo n > K se tiene que
  48.  
  49.   fibo(n) = F(n,K)
  50.  
  51.   por lo tanto tenemos:
  52.  
  53.   fibo(n) = F(n,k) = fibo(k + 1) * fibo(n - k) + fibo(k) * fibo(n - k - 1) para 0 <= k < n
  54.  
  55.  
  56.   SUCESION DE FIBONACCI OPTIMIZADA
  57.   ================================
  58.  
  59.   Escribiremos fibo(n) como  f(n), es mas corto :-)
  60.   Partiendo de la expresion F(n,k) consideraremos dos casos:
  61.  
  62.   - n par:
  63.  
  64.         Sea k = n / 2
  65.  
  66.         Asi F(n,k) = f(k + 1) f(n - k) + f(k) f(n - k - 1) =
  67.         f(n/2 + 1) f(n/2) + f(n/2) f(n/2 - 1) =
  68.         =f(n/2) (f(n/2 + 1) + f(n/2 - 1)
  69.  
  70.         F(n,n/2) = f(n / 2) * (f(n / 2 + 1) + f(n / 2 - 1)) := F(n)
  71.  
  72.     - n impar:
  73.  
  74.         Sea k = (n - 1) / 2
  75.  
  76.         F(n,k) = f(k + 1) f(n - k) + f(k) f(n - k - 1) =
  77.         f((n - 1) / 2 + 1) f((n + 1) / 2) + f((n - 1) / 2) f((n + 1) / 2 - 1) =
  78.         f((n + 1) / 2) f((n + 1) / 2) + f((n - 1) / 2) f((n - 1) / 2) =
  79.         (f((n + 1) / 2))^2 + (f((n - 1) / 2))^2
  80.  
  81.         F(n,(n - 1)/2) = (f((n + 1) / 2))^2 + (f((n - 1) / 2))^2 := F(n)
  82.  
  83.     Por lo tanto definimos la sucesion de Fibonacci como sigue:
  84.  
  85.     fibo(0) = 0
  86.     fibo(1) = 1
  87.     fibo(n) = F(n) si n > 1
  88.  
  89.     donde:
  90.         F(n) = fibo(n / 2) * (fibo(n / 2 + 1) + fibo(n / 2 - 1)) si n par
  91.         F(n) = (fibo((n + 1) / 2))^2 + (fibo((n - 1) / 2))^2     si n impar
  92.  
  93.     Observemos ahora que si n==2,
  94.  
  95.     fibo(2) = F(2) = fibo(1) * (fibo(2) + fibo(0)) = fibo(1) * fibo(2)
  96.  
  97.     y tenemos una recursion infinita, ya que para calcular fibo(2) hay que calcular fibo(2)...
  98.  
  99.     Asi pues, tenemos la definicion final de la sucesion de Fibonacci:
  100.  
  101.     fibo(0) = 0
  102.     fibo(1) = 1
  103.     fibo(2) = 1
  104.     fibo(n) = F(n) si n > 1
  105.  
  106.     con F(n) como antes.
  107.  
  108.     Definiendo fibo(n) de esta forma, en cada paso de recursion generamos dos o tres llamadas
  109.     a la misma funcion fibo, pero en cada una de ellas reducimos el tamaño del dato inicial a
  110.     la mitad, por lo que el coste computacional es mucho menor (¿Cual es el coste? No se calcularlo)
  111. */
  112.  
  113. #include <stdio.h>
  114. #include <stdlib.h>
  115. #include <time.h>
  116.  
  117. #define MIN 37
  118. #define MAX 42
  119.  
  120. typedef unsigned long long fibo_t;
  121.  
  122. unsigned long long llamadas_clasico;
  123. unsigned long long llamadas_optimizado;
  124.  
  125. fibo_t fibo_clasico(fibo_t n)
  126. {
  127.    llamadas_clasico++;
  128.  
  129.    if(n == 0)
  130.        return 0;
  131.    if(n == 1)
  132.        return 1;
  133.  
  134.    return fibo_clasico(n - 1) + fibo_clasico(n - 2);
  135. }
  136.  
  137. fibo_t fibo(fibo_t n)
  138. {
  139.    llamadas_optimizado++;
  140.  
  141.    if(n == 0)
  142.        return 0;
  143.    if(n == 1)
  144.        return 1;
  145.    if(n == 2) //Evitamos recurion infinita si n == 2
  146.        return 1;
  147.  
  148.    if(n % 2) //n impar y mayor que 2
  149.    {
  150.        fibo_t k1,k2;
  151.  
  152.        k1 = fibo((n + 1) / 2);
  153.        k2 = fibo((n - 1) / 2);
  154.  
  155.        return k1 * k1 + k2 * k2;
  156.    }
  157.  
  158.    //n par y mayor que 2
  159.    return fibo(n / 2) * (fibo((n / 2) + 1) + fibo((n / 2) - 1));
  160.    //si n == 2 fibo(n / 2) * fibo(n / 2 + 1) = fibo(1) * fibo(2)
  161.    //habria recursion infinita si no se pone n == 2 como caso base
  162. }
  163.  
  164. int main(int argc, char *argv[])
  165. {
  166.    fibo_t i,valor;
  167.    time_t ini;
  168.  
  169.    printf("Fibonacci clasico:\n");
  170.  
  171.    ini = time(NULL);
  172.  
  173.    for(i = MIN ; i < MAX ; i++)
  174.    {
  175.        llamadas_clasico = 0;
  176.        valor = fibo_clasico(i);
  177.  
  178.        printf("  fibo_clasico(%llu) = %llu (%llu llamadas)\n",i,valor,llamadas_clasico);
  179.    }
  180.  
  181.    printf("%llu segundos\n",time(NULL) - ini);
  182.  
  183.    printf("\nFibonacci optimizado:\n");
  184.  
  185.    ini = time(NULL);
  186.  
  187.    for(i = MIN ; i < MAX ; i++)
  188.    {
  189.        llamadas_optimizado = 0;
  190.        valor = fibo(i);
  191.  
  192.        printf("  fibo(%llu) = %llu (%llu llamadas)\n",i,valor,llamadas_optimizado);
  193.    }
  194.  
  195.    printf("%llu segundos\n",time(NULL) - ini);
  196.  
  197.    return 0;
  198. }
  199.  

Código
  1. #include <stdio.h>
  2.  
  3. typedef unsigned long long fibo_t;
  4.  
  5. fibo_t fibo(fibo_t n)
  6. {
  7.    if(n == 0)
  8.        return 0;
  9.    if(n == 1)
  10.        return 1;
  11.    if(n == 2)
  12.        return 1;
  13.  
  14.    if(n % 2)
  15.    {
  16.        fibo_t k1,k2;
  17.  
  18.        k1 = fibo((n + 1) / 2);
  19.        k2 = fibo((n - 1) / 2);
  20.  
  21.        return k1 * k1 + k2 * k2;
  22.    }
  23.  
  24.    return fibo(n / 2) * (fibo((n / 2) + 1) + fibo((n / 2) - 1));
  25. }
  26.  
  27. int convertir(char *s, fibo_t *valor)
  28. {
  29.    *valor = 0;
  30.  
  31.    while(*s)
  32.    {
  33.        if((*s) < '0' || (*s) > '9')
  34.        {
  35.            *valor = 0;
  36.            return 0;
  37.        }
  38.  
  39.        *valor *= 10;
  40.        *valor += (*(s++)) - '0';
  41.    }
  42.  
  43.    return 1;
  44. }
  45.  
  46. int main(int argc, char *argv[])
  47. {
  48.    int i;
  49.    fibo_t n;
  50.  
  51.    if(argc < 2)
  52.    {
  53.        fprintf(stderr,"\nLinea de comandos: %s PARAMETRO_1 [PARAMETRO_2 ... PARAMETRO_N]\n\n",argv[0]);
  54.        fprintf(stderr,"Los distintos parametros deben ser enteros positivos\n");
  55.        return 1;
  56.    }
  57.  
  58.    fprintf(stdout,"\n");
  59.  
  60.    for(i = 1 ; i < argc ; i++)
  61.    {
  62.        if(!convertir(argv[i],&n))
  63.            fprintf(stderr,"%s: parametro incorrecto\n",argv[i]);
  64.        else
  65.            fprintf(stdout,"%s(%llu) = %llu\n",argv[0],n,fibo(n));
  66.    }
  67.  
  68.    return 0;
  69. }
  70.  


En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
0xDani


Desconectado Desconectado

Mensajes: 1.077



Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #1 en: 20 Julio 2013, 20:08 pm »

Muy buen código, y de hecho si que está optimizado  :o

Cita de: Program output
Fibonacci clasico:
  fibo_clasico(37) = 24157817 (78176337 llamadas)
  fibo_clasico(38) = 39088169 (126491971 llamadas)
  fibo_clasico(39) = 63245986 (204668309 llamadas)
  fibo_clasico(40) = 102334155 (331160281 llamadas)
  fibo_clasico(41) = 165580141 (535828591 llamadas)
46 segundos

Fibonacci optimizado:
  fibo(37) = 24157817 (88 llamadas)
  fibo(38) = 39088169 (141 llamadas)
  fibo(39) = 63245986 (90 llamadas)
  fibo(40) = 102334155 (131 llamadas)
  fibo(41) = 165580141 (95 llamadas)
0 segundos


En línea

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM
amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #2 en: 20 Julio 2013, 23:11 pm »

¿46 segundos?  :huh: A mí me ha tardado 2-3 segundos el método clásico.

Excelente código, aunque voy a ser un poco troll y voy a mejorar el método clásico:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. #define MIN 37
  6. #define MAX 42
  7.  
  8. typedef unsigned long long fibo_t;
  9.  
  10. unsigned long long llamadas_clasico;
  11. unsigned long long llamadas_optimizado;
  12.  
  13. #define MAX_CACHE 33
  14.  
  15. unsigned long long Fibonaci_Cache[MAX_CACHE] = {1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597
  16. ,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,31524578};
  17.  
  18. fibo_t fibo_clasico(fibo_t n)
  19. {
  20.    llamadas_clasico++;
  21.  
  22.    if(n < MAX_CACHE)
  23.        return Fibonaci_Cache[n];
  24.  
  25.    return fibo_clasico(n - 1) + fibo_clasico(n - 2);
  26. }
  27.  
  28. fibo_t fibo(fibo_t n)
  29. {
  30.    llamadas_optimizado++;
  31.  
  32.    if(n == 0)
  33.        return 0;
  34.    if(n == 1)
  35.        return 1;
  36.    if(n == 2) //Evitamos recurion infinita si n == 2
  37.        return 1;
  38.  
  39.    if(n % 2) //n impar y mayor que 2
  40.    {
  41.        fibo_t k1,k2;
  42.  
  43.        k1 = fibo((n + 1) / 2);
  44.        k2 = fibo((n - 1) / 2);
  45.  
  46.        return k1 * k1 + k2 * k2;
  47.    }
  48.  
  49.    //n par y mayor que 2
  50.    return fibo(n / 2) * (fibo((n / 2) + 1) + fibo((n / 2) - 1));
  51.    //si n == 2 fibo(n / 2) * fibo(n / 2 + 1) = fibo(1) * fibo(2)
  52.    //habria recursion infinita si no se pone n == 2 como caso base
  53. }
  54.  
  55. int main(int argc, char *argv[])
  56. {
  57.    fibo_t i,valor;
  58.    time_t ini;
  59.  
  60.    printf("Fibonacci clasico:\n");
  61.  
  62.    ini = time(NULL);
  63.  
  64.    for(i = MIN ; i < MAX ; i++)
  65.    {
  66.        llamadas_clasico = 0;
  67.        valor = fibo_clasico(i);
  68.  
  69.        printf("  fibo_clasico(%llu) = %llu (%llu llamadas)\n",i,valor,llamadas_clasico);
  70.    }
  71.  
  72.    printf("%llu segundos\n",time(NULL) - ini);
  73.  
  74.    printf("\nFibonacci optimizado:\n");
  75.  
  76.    ini = time(NULL);
  77.  
  78.    for(i = MIN ; i < MAX ; i++)
  79.    {
  80.        llamadas_optimizado = 0;
  81.        valor = fibo(i);
  82.  
  83.        printf("  fibo(%llu) = %llu (%llu llamadas)\n",i,valor,llamadas_optimizado);
  84.    }
  85.  
  86.    printf("%llu segundos\n",time(NULL) - ini);
  87.  
  88.    return 0;
  89. }

Ala, ahora los tiempos y las llamadas deberían ser parecidos :xD
« Última modificación: 20 Julio 2013, 23:14 pm por amchacon » En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #3 en: 20 Julio 2013, 23:53 pm »

Si quieres darle una pequeña vuelta de tuerca más puedes usar los siguientes trucos:

mejor preincrementos a postincrementos:

Código
  1. // esto
  2. ++variable;
  3.  
  4. // es mas optimo que esto ( como norma general, ya que depende de las optimizaciones del compilador )
  5. variable++;[/code ]
  6.  
  7. Para dividir entre dos, es muuuucho más óptimo usar desplazamientos binarios:
  8.  
  9. [code=c]
  10. // esto
  11. variable = variable >> 1;
  12.  
  13. // es más óptimo que esto
  14. variable = variable / 2;

Esto lo podrías optimizar un pelin ( siendo quisquillosos )

Código
  1. // Con código redundante
  2. if(n == 0)
  3.    return 0;
  4. if(n == 1)
  5.    return 1;
  6. if(n == 2) //Evitamos recurion infinita si n == 2
  7.    return 1;
  8.  
  9. // Optimizado
  10. if(n == 0)
  11.    return 0;
  12. if(n <= 2) // Se evita una comprobacion en cada pasada
  13.    return 1;

Si reutilizas algún cálculo costoso, intenta precalcularlo

Código
  1. // Sin optimizar
  2. return fibo(n / 2) * (fibo((n / 2) + 1) + fibo((n / 2) - 1));
  3.  
  4. // Optimizado
  5. int temp = n / 2; // o mejor aun temp = n >> 1;
  6. return fibo( temp ) * ( fibo( temp + 1 ) + fibo( temp - 1 ) );

También creo recordar, no estoy 100% seguro, que para saber si un número es divisible entre 2 se puede optimizar también de la siguiente forma ( como no aprovechando desplazamientos binarios ):

Código
  1. // Sin optimizar
  2. if(n % 2) //n impar y mayor que 2
  3.  
  4. // optimizado
  5. if ( ( n >> 1 << 1 ) == n )

Esto último básicamente consiste en eliminar el bit de menor peso del número ... si es par, ese dígito es cero y el número permanece invariable.

Son truquillos tontos si quieres conseguir arañar hasta la última señal de reloj del procesador.

Eso si, te lo has currado, no voy a ser yo el que te quite el mérito.

Enhorabuena.[/code]
En línea

0xDani


Desconectado Desconectado

Mensajes: 1.077



Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #4 en: 21 Julio 2013, 00:49 am »

@eferion, había visto algún artículo sobre optimización de código hasta esos extremos en ensamblador, pero nunca se me había ocurrido hacerlo en C  :P Supongo que para echar el rato está bien xD

EDIT: Estos tíos sí que lo flipaban con la optimización: http://www.thehackademy.net/madchat/vxdevl/vxmags/ddt-1/DDT%231.2_G
« Última modificación: 21 Julio 2013, 01:15 am por 0xDani » En línea

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM
do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #5 en: 21 Julio 2013, 08:35 am »

EDIT: Estos tíos sí que lo flipaban con la optimización: http://www.thehackademy.net/madchat/vxdevl/vxmags/ddt-1/DDT%231.2_G

Aunque he leído muy poco, el texto parece entretenido. A ver que se cuentan.

Un amigo está haciendo un trabajo sobre como los compiladores de C (no se si se centra en gcc...) traducen a código máquina y, por lo que me dijo, hay diferencias entre variable++, ++variable,variable = variable + 1 y variable += 1. No se si todas las expresiones anteriores generan distinto código máquina o si alguna es equivalente a alguna de las otras... ¿Sabéis algo mas sobre esto?

¡Saludos!

Acabo de leerlo. No me parece demasiado interesante. Se centra sobre todo en reducir la cantidad de código máquina generado. No busca reducir el coste computacional del algoritmo. Si el código inicial tiene un orden O(n), el final tendrá el mismo, por lo que desde el punto de vista del algoritmo, no gana nada...
« Última modificación: 21 Julio 2013, 09:05 am por do-while » En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #6 en: 21 Julio 2013, 11:00 am »

Acabo de leerlo. No me parece demasiado interesante. Se centra sobre todo en reducir la cantidad de código máquina generado. No busca reducir el coste computacional del algoritmo. Si el código inicial tiene un orden O(n), el final tendrá el mismo, por lo que desde el punto de vista del algoritmo, no gana nada...
Todas las optimizaciones en ensamblador son lineales ;)

Un amigo está haciendo un trabajo sobre como los compiladores de C (no se si se centra en gcc...) traducen a código máquina y, por lo que me dijo, hay diferencias entre variable++, ++variable,variable = variable + 1 y variable += 1. No se si todas las expresiones anteriores generan distinto código máquina o si alguna es equivalente a alguna de las otras... ¿Sabéis algo mas sobre esto?
Hay una gran diferencia entre variable = variable +1  y usar los operadores de incremento. La primera expresión tienes que mover la variable en un registro, sumarle 1 y devolverlo a la memoria RAM.

La segunda expresión puede hacerse en una sola sentencia con una sentencia de esamblador (creo que era incr).

De todas formas, si activas las optimización del compilador, probablemente esto te lo haga automático.
En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
0xDani


Desconectado Desconectado

Mensajes: 1.077



Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #7 en: 21 Julio 2013, 16:56 pm »

Acabo de leerlo. No me parece demasiado interesante. Se centra sobre todo en reducir la cantidad de código máquina generado. No busca reducir el coste computacional del algoritmo. Si el código inicial tiene un orden O(n), el final tendrá el mismo, por lo que desde el punto de vista del algoritmo, no gana nada...

Claro, yo me refería más bien al tipo de optimizaciones que señalaba @eferion. Y en cuanto a las dudas de los incrementos, en un compilador moderno no tiene importancia, porque van a optimizar el código.
En línea

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM
Shout

Desconectado Desconectado

Mensajes: 191


Acid


Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #8 en: 21 Julio 2013, 18:29 pm »

@eferion
Realmente no tiene sentido lo de num >> 1 para dividir entre 2.
Lo digo por esto:

Son 1.000.000.000 iteraciones  :silbar: :silbar:

En este benchmark, ">>" ha tardado más, pero seguramente es porque tengo un montón de cosas abiertas, ya que antes no tenía abierto nada (ni siquiera VC++) y ">>" fue un poco más rápido (0.05 segundos), pero aún así creo que no vale la pena complicar el código (legibilidad) por 0.1 segundos. Recuerda, no son 1.000 ni 1.000.000 iteraciones, son ¡1.000.000.000!
En línea

I'll bring you death and pestilence, I'll bring you down on my own
rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Sucesion de Fibonacci recursiva optimizada
« Respuesta #9 en: 21 Julio 2013, 19:17 pm »

Para dividir entre dos, es muuuucho más óptimo usar desplazamientos binarios:
Código
  1. // esto
  2. variable = variable >> 1;
  3.  
  4. // es más óptimo que esto
  5. variable = variable / 2;
En el desplazamiento si la variable es de un tipo entero con signo el valor del bit de relleno depende de la implementación, en otras palabras no esta garantizado que el resultado de ambas operaciones (división y desplazamiento) sea el mismo. Si es un tipo sin signo el bit de relleno siempre es cero, ahí no hay problema.

También creo recordar, no estoy 100% seguro, que para saber si un número es divisible entre 2 se puede optimizar también de la siguiente forma ( como no aprovechando desplazamientos binarios ):

Código
  1. // Sin optimizar
  2. if(n % 2) //n impar y mayor que 2
  3.  
  4. // optimizado
  5. if ( ( n >> 1 << 1 ) == n )
Ya que los números pares (positivos) tienen el bit menos significativo a cero se puede reducir la expresión a "!(n & 1)". Y si invertimos la condición (verificar impares) terminamos utilizando un operador:
Código
  1. if (n & 1){
  2.   /* impares */
  3. }else {
  4.   /* pares */
  5. }

Pero como ya se comento es mejor dejar ciertas mejoras (por ejemplo división vs desplazamiento) al compilador.

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Sucesión Fibonacci [Batch] « 1 2 »
Scripting
leogtz 17 15,197 Último mensaje 15 Junio 2009, 17:26 pm
por leogtz
[Código-Ruby]Sucesión Fibonacci - JaAViEr
Scripting
0x5d 0 2,745 Último mensaje 8 Enero 2012, 08:57 am
por 0x5d
Duda en el código (porgrama sucesión de Fibonacci)
Programación C/C++
b_rabbit10 2 2,606 Último mensaje 18 Febrero 2013, 22:15 pm
por b_rabbit10
[Perl] Ejemplo de Sucesion Fibonacci
Scripting
BigBear 0 2,644 Último mensaje 5 Diciembre 2014, 15:04 pm
por BigBear
Cómo conseguir una red inalámbrica optimizada
Noticias
wolfbcn 0 1,097 Último mensaje 27 Octubre 2016, 14:53 pm
por wolfbcn
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines