Lo que quería preguntaros es el asunto de Perl...
Comparativa entre lenguajes I
Vamos a ir realizando una comparativa entre varios lenguajes de programación.
Estos serán C, Perl, Python y Ruby.
Elegimos C porque es un lenguaje de nivel medio que nos dará un buen tope de eficiencia. Utilizaremos programas sencillos para que la habilidad como programador influya lo menos posible.
Tampoco nos importa la eficiencia. Se trata de una comparativa en tiempos de ejecución, no de realmente comparar lenguajes.
El primer programa consistirá en mostrar los primeros 33 números de Fibonacci. El último número calculado es 3524578.
Primero utilizaremos una implementación recursiva. Mostraremos además el número de llamadas a la función, que debería ser independiente del lenguaje.
También es de esperar que las funciones recursivas tarden más, ya que estamos haciendo simples sumas y al hacerlo recursivo añadimos complejidad.
RECURSIVO
Códigos
Using c Syntax Highlighting
#include
long int llamadas=0;
int fibonacci(int n) {
llamadas++;
if (n==0 | n==1)
return 1;
else
return fibonacci(n-1) + fibonacci(n-2);
}
main() {
int i;
for (i=0; i<33;i++)>
printf("%d \n", llamadas);
}
long int llamadas=0;
int fibonacci(int n) {
llamadas++;
if (n==0 | n==1)
return 1;
else
return fibonacci(n-1) + fibonacci(n-2);
}
main() {
int i;
for (i=0; i<33;i++)>
printf("%d \n", llamadas);
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Using ruby Syntax Highlighting
#!/usr/bin/ruby
$llamadas=0
def fibonacci(n)
$llamadas+=1
return 1 if n==1 or n==0
fibonacci(n-1)+fibonacci(n-2)
end
33.times { |num| puts fibonacci(num).to_s }
puts $llamadas.to_s
$llamadas=0
def fibonacci(n)
$llamadas+=1
return 1 if n==1 or n==0
fibonacci(n-1)+fibonacci(n-2)
end
33.times { |num| puts fibonacci(num).to_s }
puts $llamadas.to_s
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4
Using perl Syntax Highlighting
#!/usr/bin/perl
$llamadas=0;
sub fibonacci {
$llamadas++;
my $n = shift;
return $n if ( $n == 0 or $n == 1 );
return fibonacci( $n-1 ) + fibonacci( $n-2 );
}
for ($num=0; $num < n="=" n="=" llamadas="0" n="=" n="=" fibo="fibonacci">
$llamadas=0;
sub fibonacci {
$llamadas++;
my $n = shift;
return $n if ( $n == 0 or $n == 1 );
return fibonacci( $n-1 ) + fibonacci( $n-2 );
}
for ($num=0; $num < n="=" n="=" llamadas="0" n="=" n="=" fibo="fibonacci">
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Using python Syntax Highlighting
#!/usr/bin/python
llamadas=0
def fib(n):
global llamadas
llamadas+=1
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
for i in range(34):
print fib(i)
print llamadas
llamadas=0
def fib(n):
global llamadas
llamadas+=1
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
for i in range(34):
print fib(i)
print llamadas
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Tiempos
- Código: Seleccionar todo
C: 18454895 llamadas
real 0m0.636s
user 0m0.628s
sys 0m0.004s
Ruby: 18454895 llamadas
real 1m12.161s
user 1m4.044s
sys 0m8.093s
Perl: 29860668 llamadas !!!
real 1m5.042s
user 1m5.000s
sys 0m0.012s
Python: 18454895 llamadas
real 0m29.577s
user 0m29.562s
sys 0m0.004s
ITERATIVO
Códigos
Using c Syntax Highlighting
#include
int fib (int n)
{
if (n==0 | n==1) return 1;
int a = 1, b = 1;
int i;
for (i = 3; i <= n; ++i) { int a_prev = a; a = b; b += a_prev; } return b; } main() { int i; for (i=0; i<34;i++) printf("%d \n", fib(i)); }
int fib (int n)
{
if (n==0 | n==1) return 1;
int a = 1, b = 1;
int i;
for (i = 3; i <= n; ++i) { int a_prev = a; a = b; b += a_prev; } return b; } main() { int i; for (i=0; i<34;i++) printf("%d \n", fib(i)); }
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
Using ruby Syntax Highlighting
#!/usr/bin/ruby
def fibonacci(n)
curr = 1 succ = 1
n.times do |i|
curr, succ = succ, curr + succ
end
return curr
end
33.times { |num| puts fibonacci(num).to_s }
def fibonacci(n)
curr = 1 succ = 1
n.times do |i|
curr, succ = succ, curr + succ
end
return curr
end
33.times { |num| puts fibonacci(num).to_s }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Using python Syntax Highlighting
#!/usr/bin/python
def fib(n): a, b = 1, 1 for i in range(n): a, b = b, a + b return a for i in range(33): print fib(i)
def fib(n): a, b = 1, 1 for i in range(n): a, b = b, a + b return a for i in range(33): print fib(i)
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Using perl Syntax Highlighting
#!/usr/bin/perl -w
sub fibonacci
{
my ($n, $a, $b) = (shift, 1, 1);
($a, $b) = ($b, $a + $b) while $n-- > 0;
$a;
}
for ($num=0; $num < 33; $num++) {
print fibonacci($num) ."\n";
}
sub fibonacci
{
my ($n, $a, $b) = (shift, 1, 1);
($a, $b) = ($b, $a + $b) while $n-- > 0;
$a;
}
for ($num=0; $num < 33; $num++) {
print fibonacci($num) ."\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Tiempos
- Código: Seleccionar todo
C:
real 0m0.002s
user 0m0.000s
sys 0m0.000s
Ruby:
real 0m0.012s
user 0m0.008s
sys 0m0.000s
Python:
real 0m0.028s
user 0m0.012s
sys 0m0.008s
Perl:
real 0m0.010s
user 0m0.004s
sys 0m0.004s
Vemos la potencia de C y que la recursividad se paga caro.
Extraña el numero de llamadas que hacer Perl, y que en modo iterativo Python sea más lento. Aun así parece el más rápido de los lenguajes interpretados.
Lo que más me extraña es lo de Perl. Lo comprobé varias veces y siempre salian una cantidad de llamadas
superior al resto.
¿A alguien se le ocurre el por qué?