Voy hacer un benckmark de 3 implementaciones de factorial:
Em primer lugar, la implementación más simple y eficiente, por siempre de los jamases, al menos para arquitecturas de Von Newman y monoprocesador:
long factorial_iterativo(long n) { long i, ac = 1; for(i=n; i>0; i--) ac = ac * i; return ac; }
Despues esta la recursiva lineal, típico ejemplo de recursividad. Fijaos en la linea de la llamada recursiva …
long factorial_recursivo(long n) { if (n == 0) return 1; else return n * factorial_recursivo(n-1); }
Y esta es la que realmente tenía curiosidad de comparar. Es un tipo de recursividad que hace que la vuelta en lugar de ser de pila, sea de cola. Es necesario modificar la interfaz y crear una nueva función manejadora que respete la interfaz. Se trata de ir acumulando el resultado como parametro y principalmente que en la linea que se hace la llamada recursiva, solo haya una llamada recursiva.
Esta función, teoricamente implementado en Caml el compilador al pasarlo a código maquina la pasa a iterativa automaticamente. Si esto fuera tambien así en C, podríamos utilizar funciones recursivas, sin miedo a desbordar la pila y sin problemas de redimiento. Y por supuesto ganando la claridad de resolver algunos problemas de naturaleza recursiva.
long _factorial_recursivo_PA(long n, long r) { if (n==0) return r; else return _factorial_recursivo_PA(n-1, n*r); } long factorial_recursivo_PA(long n) { return _factorial_recursivo_PA(n, 1); }
Los resultados son estos:
Seguir leyendo
Filed under: compiladores, programación | Tagged: benchmark, c#, factorial, Linux, recursividad, señales | Leave a comment »