On Thu, 15 Jul 2010 04:38:22 -0700 (PDT)
Brisance <cru...@gmail.com> wrote:

> Here's a factorial function as found in the WikiBook "Learning
> Clojure" <http://en.wikibooks.org/wiki/Learning_Clojure>:
> 
> (defn factorial [n]
>   (defn fac [n acc]
>     (if (zero? n)
>        acc
>       (recur (- n 1) (* acc n)))) ; recursive call to fac, but reuses
> the stack; n will be (- n 1), and acc will be (* acc n)
>   (fac n 1))
> 
> Question: how would I go about writing idiomatic Clojure to return
> factorials of n, for large values of n. e.g. 1e6 or more? Preferably
> without having to create another function.

Well, an idiomatic refactoring of the above might be:

(defn factorial [n]
      (reduce * (range 1 (inc n)))

However, that won't be able to calculate 1000000! on my hardware, as
that has over five and a half billion digits, and I only have 4Gig of
ram. If you actually want to see the value - well, that's a lot of
paper. Or phosphor, or whatever. If you'll settle for an seeing an
approximation, this works:

(defn fact-approx
  "Approximate factorial values as strings representing floats. We output
   strings since we can build the string for output values to large to be 
   represented in floats. Works for n less than 10 billion."

  [n] (apply (fn [val exp]
               (let [valstr (str val)]
                 (str (subs valstr 0 (min 6 (count valstr))) "E" exp)))
             (let [x (+ n n 1) ex 0.0]
               (if (> x 1)
                 (let [t 
                       (/ (- (+ (Math/log (* 2.0 Math/PI))
                                (* (Math/log (/ x 2.0)) x))
                             x
                             (/ (- 1.0 (/ 7.0 (* 30.0 x x))) (* 6.0 x)))
                          2.0
                          (Math/log 10))
                       ex (int t)]
                   [(Math/pow 10 (- t ex)), ex] )
                 [x, 0]))))

It's not clear you'd call it idiomatic; I haven't seen enough
hard-core mathematical calculations to have a feel for what would be
considered idiomatic.

If you really need to work with accurate values of n! for these values
of n (and have the hardware to deal with them), googling for "fast
factorial" turns up some Java objects that might be of interest.

      <mike
-- 
Mike Meyer <m...@mired.org>             http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to