How to do exponentiation in clojure?

前端 未结 13 1800
执笔经年
执笔经年 2021-01-30 12:32

How can I do exponentiation in clojure? For now I\'m only needing integer exponentiation, but the question goes for fractions too.

相关标签:
13条回答
  • 2021-01-30 12:34

    Try

    (defn pow [x n]
      (loop [x x n n r 1]
        (cond
          (= n 0) r
          (even? n) (recur (* x x) (/ n 2) r)
          :else (recur x (dec n) (* r x)))))
    

    for a tail-recursive O(log n) solution, if you want to implement it yourself (only supports positive integers). Obviously, the better solution is to use the library functions that others have pointed out.

    0 讨论(0)
  • 2021-01-30 12:37

    You can use java's Math.pow or BigInteger.pow methods:

    (Math/pow base exponent)
    
    (.pow (bigint base) exponent)
    
    0 讨论(0)
  • 2021-01-30 12:39

    Implementation of "sneaky" method with tail recursion and supporting negative exponent:

    (defn exp
      "exponent of x^n (int n only), with tail recursion and O(logn)"
       [x n]
       (if (< n 0)
         (/ 1 (exp x (- n)))
         (loop [acc 1
                base x
                pow n]
           (if (= pow 0)
             acc                           
             (if (even? pow)
               (recur acc (* base base) (/ pow 2))
               (recur  (* acc base) base (dec pow)))))))
    
    0 讨论(0)
  • 2021-01-30 12:43

    Clojure has a power function that works well: I'd recommend using this rather than going via Java interop since it handles all the Clojure arbitrary-precision number types correctly. It is in namespace clojure.math.numeric-tower.

    It's called expt for exponentiation rather than power or pow which maybe explains why it's a bit hard to find ... anyway here's a small example (note that use works but better use require):

    (require '[clojure.math.numeric-tower :as math :refer [expt]])  ; as of Clojure 1.3
    ;; (use 'clojure.contrib.math)     ; before Clojure 1.3
    
    (expt 2 200)
    => 1606938044258990275541962092341162602522202993782792835301376
    

    Reminder about package installation

    You must first install the Java package org.clojure.math.numeric-tower to make the Clojure namespace clojure.math.numeric-tower accessible!

    On the command line:

    $ lein new my-example-project
    $ cd lein new my-example-project
    

    Then edit project.clj and add [org.clojure/math.numeric-tower "0.0.4"] to the dependencies vector.

    Start a lein REPL (not a clojure REPL)

    $ lein repl
    

    Now:

    (require '[clojure.math.numeric-tower :as math])
    (math/expt 4 2)
    ;=> 16
    

    or

    (require '[clojure.math.numeric-tower :as math :refer [expt]])
    (expt 4 2)
    ;=> 16
    
    0 讨论(0)
  • 2021-01-30 12:45

    How about clojure.contrib.genric.math-functions

    There is a pow function in the clojure.contrib.generic.math-functions library. It is just a macro to Math.pow and is more of a "clojureish" way of calling the Java math function.

    http://clojure.github.com/clojure-contrib/generic.math-functions-api.html#clojure.contrib.generic.math-functions/pow

    0 讨论(0)
  • 2021-01-30 12:47

    When this question was originally asked, clojure.contrib.math/expt was the official library function to do this. Since then, it has moved to clojure.math.numeric-tower

    0 讨论(0)
提交回复
热议问题