sábado, 16 de junho de 2012

Simplificação do código para ser otimizado


Um problema de matemática chamou-me a atenção e encontrei a solução usando a soma de uma P.A. O enunciado é este:


Seja
f(n)=n se n<10
f(n)=multiplicação dos algarismos se n>=10
Então f(1)+f(2)+f(3)+...+f(100) é igual a?

Decidi fazer um programa e o principal deste texto não é o programa que resolve este problema. É como o conhecimento pode simplificar o processamento e resolver em menos tempo além de comparar o desempenho de duas linguagens de programação.

Primeiro foi feito em shell script. No bloco for i in `seq 10 1 99` existem duas variáveis que armazenam os algarismos do número. O comando cut -c 1 associa a dezena à variável valor1 e cut -c 2 associa a unidade à variável valor2. A variável multiplicado armazena o produto enquanto que soma acumula os resultados de multiplicado.


#!/bin/bash 

for i in `seq 9`
   do 
      let soma1=$soma1+$i  
   done  
 
for i in `seq 10 1 99`  
   do  
      valor1=`echo $i | cut -c 1`  
      valor2=`echo $i | cut -c 2` 
      multiplicado=`echo "$valor1 * $valor2" | bc`  
      let soma2=$soma2+$multiplicado  
   done 
  
let soma=$soma1+$soma2 echo Resultado $soma

Executando o script junto com o comando time tenho a resposta que levou para efetuar os cálculos:

 

 
Resultado 2070

real 0m0.704s
user 0m0.036s
sys 0m0.028s

Encontrada a solução em uma linguagem, quis testar em C++. No entanto como não consegui separar as dezenas e unidades em duas variáveis, encontrei uma solução mais simples. E para que a comparação seja válida, é preciso que os programas executem as mesmas rotinas.

Usando dois laços for separam-se as dezenas e unidades. A otimização em shell script é apresentada abaixo:

   
#!/bin/bash  

for i in `seq 9`
   do  
      let soma1=$soma1+$i  
   done  

for dezena in `seq 9`  
  do  
    for unidade in `seq 9`  
      do  
        resultado=$dezena*$unidade  
        let soma2=$soma2+$resultado 
      done  
  done  

let soma=$soma1+$soma2  
echo Resultado $soma  


Resultado 2070

real 0m0.041s
user 0m0.004s
sys 0m0.012s

Por fim, testa-se em C++.

Como foi dito, elaborei a lógica deste código antes do segundo shell script. As explicações são as mesmas do código anterior.

 
# include <iostream>  
using namespace std;  
int main()  
{  
   int dezena, unidade;  
   int soma1=0, soma2=0;
  
   for (int i=1; i<10; i++)  
      soma1+=i;  

   for (dezena=1; dezena<10; dezena++) 
   {  
      for (unidade=1; unidade<10; unidade++) 
      { 
        soma2+=dezena*unidade; 
      } 
   } 
 
   cout << "Resultado " << soma1+soma2; 
   cout << endl; 
 
   return 0; 
}  


Resultado 2070

real 0m0.004s
user 0m0.000s
sys 0m0.000s


Resumo dos tempos:

Shell Script Shell Script (com otimização) C++
0.704s 0.041s 0.004s

Conclusão: cada linguagem tem a sua particularidade. Para desenvolver algo rápido considero que o shell script é uma ferramenta que atende muito bem. Por outro lado, se for preciso alto desempenho, o C++ é insuperável*. Adicionalmente, fica claro que o resultado do que é compilado é mais rápido do que interpretado.
* De acordo com o professor doutor José Luis Zem da disciplina de Arquitetura e Organização de Computadores, a linguagem Fortran tem desempenho superior além de maior capacidade de ponto flutuante.

Agradeço ao professor Zem por explicar a diferença de desempenho entre compilado e interpretado. No caso do interpretado há um outro programa analisando cada linha do script e transformando em instruções de computador. No caso dos compilados, o compilador usa regras de otimização para gerar o binário.