How to do exponentiation in clojure?

前端 未结 13 1802
执笔经年
执笔经年 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:50

    classic recursion (watch this, it blows stack)

    (defn exp [x n]
         (if (zero? n) 1
             (* x (exp x (dec n)))))
    

    tail recursion

    (defn exp [x n]
      (loop [acc 1 n n]
        (if (zero? n) acc
            (recur (* x acc) (dec n)))))
    

    functional

    (defn exp [x n]
      (reduce * (repeat n x)))
    

    sneaky (also blows stack, but not so easily)

    (defn exp-s [x n]
      (let [square (fn[x] (* x x))]
        (cond (zero? n) 1
              (even? n) (square (exp-s x (/ n 2)))
              :else (* x (exp-s x (dec n))))))
    

    library

    (require 'clojure.contrib.math)
    
    0 讨论(0)
  • 2021-01-30 12:51

    I think this would work too:

    (defn expt [x pow] (apply * (repeat pow x)))
    
    0 讨论(0)
  • 2021-01-30 12:51

    A simple one-liner using reduce:

    (defn pow [a b] (reduce * 1 (repeat b a)))
    
    0 讨论(0)
  • 2021-01-30 12:55

    If you really need a function and not a method you can simply wrap it:

     (defn pow [b e] (Math/pow b e))
    

    And in this function you can cast it to int or similar. Functions are often more useful that methods because you can pass them as parameters to another functions - in this case map comes to my mind.

    If you really need to avoid Java interop, you can write your own power function. For example, this is a simple function:

     (defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
       (if (neg? p) (/ 1 result) result)))
    

    That calculates power for integer exponent (i.e. no roots).

    Also, if you are dealing with large numbers, you may want to use BigInteger instead of int.

    And if you are dealing with very large numbers, you may want to express them as lists of digits, and write your own arithmetic functions to stream over them as they calculate the result and output the result to some other stream.

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

    SICP inspired full iterative fast version of 'sneaky' implementation above.

    (defn fast-expt-iter [b n]
      (let [inner (fn [a b n]
                    (cond
                      (= n 0) a
                      (even? n) (recur a (* b b) (/ n 2))
                      :else (recur (* a b) b (- n 1))))
            ]
        (inner 1 b n)))
    
    0 讨论(0)
  • 2021-01-30 12:58

    Use clojure.math.numeric-tower, formerly clojure.contrib.math.


    API Documentation


    (ns user
      (:require [clojure.math.numeric-tower :as m]))
    
    (defn- sqr
      "Uses the numeric tower expt to square a number"
      [x]
      (m/expt x 2))
    
    0 讨论(0)
提交回复
热议问题