如何在clojure中求幂?

我怎么能在clojure中求幂? 现在我只需要整数求幂,但问题也适用于分数。

经典recursion(看这个,它吹堆栈)

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

尾recursion

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

实用

 (defn exp [xn] (reduce * (repeat nx))) 

偷偷摸摸(也吹堆栈,但不是那么容易)

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

图书馆

 (require 'clojure.contrib.math) 

Clojure有一个很好的function函数:我build议使用它而不是通过Java interop,因为它正确处理所有的Clojure任意精度数字types。

这就是所谓的exptexponentiation而不是powerpow ,这可能解释了为什么有点难以find…..无论如何,这里是一个小例子:

 (use 'clojure.contrib.math) (expt 2 200) => 1606938044258990275541962092341162602522202993782792835301376 

从Clojure 1.3开始,这个函数和其他相关的math函数已经移动了,所以你需要这样做:

 (use 'clojure.math.numeric-tower) 

您可以使用java的Math.powBigInteger.pow方法:

 (Math/pow base exponent) (.pow (bigint base) exponent) 

当这个问题最初被问到, http://clojure.github.com/clojure-contrib/math-api.html#clojure.contrib.math/expt是官方库函数所在的地方。 从那以后,它已经转移到https://github.com/clojure/math.numeric-tower/blob/master/src/main/clojure/clojure/math/numeric_tower.clj#L80

 user=> (.pow (BigInteger. "2") 10) 1024 user=> (.pow (BigInteger. "2") 100) 1267650600228229401496703205376 

如果你真的需要一个函数,而不是一个方法,你可以简单地包装它:

  (defn pow [be] (Math/pow be)) 

在这个函数中,你可以把它转换为int或类似的。 函数往往更有用的方法,因为你可以将它们作为parameter passing给另一个函数 – 在这种情况下, map出现在我的脑海里。

如果您真的需要避免Java互操作,您可以编写自己的电源function。 例如,这是一个简单的function:

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

计算整数指数(即无根)的功率。

另外,如果你正在处理大量的数据,你可能想要使用BigInteger而不是int

如果您处理的数字非常大 ,您可能希望将它们表示为数字列表,并且编写自己的算术函数来在它们计算结果时输出,并将结果输出到其他数据stream。

我认为这也会起作用:

 (defn expt [x pow] (apply * (repeat pow x))) 

SICP启发了上面“偷偷摸摸”实现的完整迭代快速版本。

 (defn fast-expt-iter [bn] (let [inner (fn [abn] (cond (= n 0) a (even? n) (recur a (* bb) (/ n 2)) :else (recur (* ab) b (- n 1)))) ] (inner 1 bn))) 

使用clojure.math.numeric-tower ,以前clojure.contrib.math


API文档


 (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)) 

尝试

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

对于一个尾recursion的O(log n)解决scheme,如果你想自己实现它(只支持正整数)。 显然,更好的解决scheme是使用其他人指出的库函数。

实施具有尾recursion和支持负指数的“偷偷摸摸”方法:

 (defn exp "exponent of x^n (int n only), with tail recursion and O(logn)" [xn] (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))))))) 

如何clojure.contrib.genric.mathfunction

clojure.contrib.generic.math-functions库中有一个pow函数。 它只是Math.pow的一个macros,更像是一种调用Javamath函数的“clojureish”方法。

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

一个简单的单行使用减less

 (defn pow [ab] (reduce * 1 (repeat ba)))