如何在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。
这就是所谓的expt
为exponentiation而不是power
或pow
,这可能解释了为什么有点难以find…..无论如何,这里是一个小例子:
(use 'clojure.contrib.math) (expt 2 200) => 1606938044258990275541962092341162602522202993782792835301376
从Clojure 1.3开始,这个函数和其他相关的math函数已经移动了,所以你需要这样做:
(use 'clojure.math.numeric-tower)
您可以使用java的Math.pow
或BigInteger.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”方法。
一个简单的单行使用减less
(defn pow [ab] (reduce * 1 (repeat ba)))