Hubiera quedado mejor como se indica
aquí.
Mucho más interesante es hacerlo de forma recursiva, siguiendo la definición de la serie:
Using perl Syntax Highlighting
#!/usr/bin/perl
use v5.16;
sub fib {
my $n = $_[0];
if ($n == 1 or $n == 0) {
return $n;
}
else {
return fib($n - 1) + fib($n - 2); # Un número de la serie es igual a la suma de los dos anteriores
}
}
say fib(34);
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Calcular el número de Fibonnaci que está en la posición 34 me tarda con mi ordenador unos 16 segundos:
Using text Syntax Highlighting
> time ./kk.pl
5702887
real 0m27.602s
user 0m16.006s
sys 0m0.120s
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
Y los tiempos aumentan de forma logarítmica para cada número superior.
Eso es debido a que se calcula varias veces el mismo número de la secuencia.
Por ejemplo, para calcular
fib(5), se debe calcular el valor de
fib(4)+fib(3), que se traduce en calcular
fib(3)+fib(2)+fib(2)+fib(1), que a su vez se traduce en
fib(2)+fib(1)+fib(1)+fib(0)+fib(1)+fib(0)+1, con lo que queda en
fib(1)+fib(0)+1+1+0+1+0+1 = 1+0+1+1+0+1+1 = 5Vemos que hemos tenido que calcular varias veces el mismo número (fib(3), dos veces).
Éste ejemplo sí que puede servir para medir el rendimiento de los distintos lenguajes, aunque solo para ver la velocidad de cálculo (y no otras cosas).
Y es aquí donde se demuestra la potencia de Perl: basta unos pequeños cambios...
Using perl Syntax Highlighting
use Memoize;
memoize('fib');
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
y ahora las prestaciones cambian extraordinariamente:
Using text Syntax Highlighting
> time ./kk.pl
5702887
real 0m0.423s
user 0m0.124s
sys 0m0.016s
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
¡¡Un poco más de una décima de segundo!!
Gracias a la ayuda del módulo Memoize (incluido con la distribución principal), vamos recordando los valores de la secuencia, con lo que solo se calculan una vez.
Finalmente, para calcular igual a como lo indica el artículo enlazado, se pueden seguir las recomendaciones del enlace que puse antes:
Using perl Syntax Highlighting
#!/usr/bin/perl
use v5.16;
sub fib {
my $n = $_[0];
return $n == 0 ? 0 : fib2($n, 0, 1);
}
sub fib2 {
my($n, $p0, $p1) = @_;
if ($n == 1) {
print "$p1\n";
}
else {
my $p2 = $p0 + $p1;
print "$p2 ";
fib2($n - 1, $p1, $p2);
}
}
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Esta forma de calcular sigue la misma idea del autor del artículo enlazado: calculamos el siguiente número de la secuencia, sabiendo ya los dos anteriores. Y separando el caso especial del cálculo de 0. Y los tiempos de ejecución son igual de buenos. Por eso para medir las prestaciones de un lenguaje es interesante que los programas hagan muchos cálculos y operaciones diversas, y repetirlo muchas veces.
También, no quedaría completo el análisis, si dejáramos fuera los tiempos de compilación, los tiempos de desarrollo, memoria consumida,
número de líneas...
The Computer Language Benchmarks GameArtículo (en inglés) Análisis gráfico de prestaciones (velocidad, consumo de recursos)