À propósito, ikarus Scheme, um compilador nativo incremental usando
GMP, parece dar uma performance excelente mesmo para o fatorial
simples, melhor que SBCL:

namekusei...@nameku:~$ ikarus
Ikarus Scheme version 0.0.3
Copyright (c) 2006-2008 Abdulaziz Ghuloum

> (define (fact n)
        (let f ((n n) (r 1))
          (if (< n 2) r (f (- n 1) (* r n)))))
> (time (and (fact 100000) #t))
running stats for (and (fact 100000) #t):
    2405 collections
    4988 ms elapsed cpu time, including 664 ms collecting
    4990 ms elapsed real time, including 691 ms collecting
    9931119600 bytes allocated
#t


namekusei...@nameku:~$ sbcl
This is SBCL 1.0.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (defun fact (n &optional (r 1))
        (if (< n 2) r
                (fact (1- n) (* r n))))

FACT
* (time (and (fact 100000) t))

Evaluation took:
  9.696 seconds of real time
  9.192575 seconds of user run time
  0.504031 seconds of system run time
  [Run times include 0.904 seconds GC run time.]
  0 calls to %EVAL
  0 page faults and
  9,931,045,056 bytes consed.
T

postei sobre isso em comp.lang.lisp e comp.lang.scheme... mas
provavelmente o mérito é mais da GMP mesmo, pusta biblioteca, ainda
mais quando acessada de uma linguagem de alto nível. :)

On Apr 30, 4:27 am, namekuseijin <[email protected]> wrote:
> On Apr 30, 2:43 am, tarcisio praciano-pereira
>
>
>
> <[email protected]> wrote:
> > Eras, Pedro! explica o código - put some comments!  Não entendi nada, e
> > sou matemático.
>
> > Aparentemente fazes alguma seleção entre par e impar, mas não entendi
> > porque.
> > > (defun ! (n)
> > >   (let ((shift 0))
> > >     (labels ((fact1 (n m)
> > >                (cond
> > >                  ((and (evenp n) (> m 1))
> > >                   (incf shift (ash n -1))
> > >                   (fact1 (ash n -1) (ash m -1)))
> > >                  ((<= n m) n)
> > >                  (t (* (fact1 n (ash m 1)) (fact1 (- n m)(ash m 1)))))))
> > >       (ash (fact1 n 1) shift))))
>
> > > pedro
>
> Ele usou otimização com bitshifting, uma operação a nível de máquina.
> Não é pra ser compreendido para não iniciados. ;)
>
> Fatorial é aquela definição recursiva e simples (e não otimizada) de
> sempre:
> (defun fatorial (n)
>   (if (< n 2) 1
>      (* n (fatorial (- n 1)))))
>
> Exceto que uma implementação puramente recursiva desse tipo
> rapidamente chega a um limite de execução:  a pilha estoura por haver
> muitas chamadas para ns muito grandes.  A solução simples em
> programação funcional é usar o estilo de tail calls (que a maioria das
> implementações suporta).
>
> Nesse estilo, elimina-se a necessidade de se manter várias chamadas em
> aberto na pilha ao se eliminar a espera pelo termino de uma
> computação:  a última chamada (tail call) é realmente uma chamada, não
> uma expressão esperando pelo resultado de uma chamada.  Como nada
> exceto a chamada original da função espera pelo seu resultado final,
> por baixo dos panos pode-se simplesmente, a grosso modo, eliminar todo
> o artefato de chamadas reais de função e compilá-la como se fosse uma
> simples iteração ou um goto nomeado.  Não se gasta pilha de chamadas.
>
> Ilustrando:
>
>   (if (< n 2) 1 ; <- expressão final
>      (* n (fatorial (- n 1))))) ; <- expressão final esperando pelo
> resultado da chamada recursiva
>
> a troca é simples e o benefício é imenso:
>   (if (< n 2) 1
>      (fatorial (- n 1)  (* n)))) ; trazemos a expressão final como um
> parâmetro para a própria chamada
>
> mas está incompleto, pois o resultado de (fatorial (- n 1)) ainda não
> foi calculado e não podemos portanto multiplicá-lo a n, certo?  Bem,
> digamos que possamos e chamemos a ele de resultado:
>
>   (if (< n 2) resultado ; <- aqui
>      (fatorial (- n 1)  (* n resultado)))) ; <- e aqui
>
> agora vamos dar um valor inicial a resultado, que por acaso vai ser o
> mesmo para a condição de parada original: 1
>
> (defun fatorial (n &optional (resultado 1))
>   (if (< n 2) resultado
>      (fatorial (- n 1)  (* n resultado))))
>
> Bem, devo dizer que esse SBCL realmente é um bicho parrudo.  Executou
> (and (fatorial 100000) t) em 9,8 segundos.  Gambit, uma das mais
> potentes implementações para Scheme, ficou na marca de 32 segundos
> para uma implementação similar:
>
> (define (fatorial n)
>   (define (! n r) (if (< n 2) r (! (- n 1) (* r n))))
>   (! n 1))
>
> 3 x mais lento...  por outro lado, gera C portável. :)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lisp-br" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/lisp-br?hl=en
-~----------~----~----~----~------~----~------~--~---

Responder a