我该如何在Clojure中求幂?现在,我只需要整数幂,但是问题也适用于分数。
我该如何在Clojure中求幂?现在,我只需要整数幂,但是问题也适用于分数。
Answers:
经典递归(观看此文章,它会发散堆栈)
(defn exp [x n]
(if (zero? n) 1
(* x (exp x (dec n)))))
尾递归
(defn exp [x n]
(loop [acc 1 n n]
(if (zero? n) acc
(recur (* x acc) (dec n)))))
功能性
(defn exp [x n]
(reduce * (repeat n x)))
偷偷摸摸的(也打击堆栈,但不那么容易)
(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))))))
图书馆
(require 'clojure.contrib.math)
Clojure具有强大的功能,可以很好地发挥作用:我建议您使用此函数,而不要通过Java interop,因为它可以正确处理所有Clojure任意精度数字类型。它在命名空间clojure.math.numeric-tower中。
它被称为expt
求幂而不是power
或pow
可能解释了为什么很难找到它的原因……无论如何,这是一个小例子(请注意,它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
您必须首先安装Java软件包,org.clojure.math.numeric-tower
以使Clojure名称空间clojure.math.numeric-tower
可访问!
在命令行上:
$ lein new my-example-project
$ cd lein new my-example-project
然后编辑project.clj
并添加[org.clojure/math.numeric-tower "0.0.4"]
到依赖向量。
启动lein REPL(不是clojure REPL)
$ lein repl
现在:
(require '[clojure.math.numeric-tower :as math])
(math/expt 4 2)
;=> 16
要么
(require '[clojure.math.numeric-tower :as math :refer [expt]])
(expt 4 2)
;=> 16
您可以使用Java Math.pow
或BigInteger.pow
方法:
(Math/pow base exponent)
(.pow (bigint base) exponent)
Math/pow
比math-pow
如何存在clojure等效物更复杂。如果已经有一个简单的java方法可以执行您想要的操作,则没有理由在clojure中重新创建功能。Java互操作并不是天生有害的。
最初提出此问题时,clojure.contrib.math / expt是执行此操作的官方库函数。从那时起,它已移至clojure.math.numeric-tower
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
(.pow 2M 100)
(Math/pow Math/E x)
就可以了(取代Math/E
您选择的基础)。
如果您确实需要一个函数而不是一个方法,则可以将其包装:
(defn pow [b e] (Math/pow b e))
在此功能中,您可以将其强制转换为int
或类似。函数通常比方法有用,因为您可以将它们作为参数传递给另一个函数-在这种情况下map
,我想到了。
如果确实需要避免Java互操作,则可以编写自己的幂函数。例如,这是一个简单的函数:
(defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
(if (neg? p) (/ 1 result) result)))
这将计算整数指数(即无根)的幂。
另外,如果要处理大量数字,则可能要使用BigInteger
而不是int
。
而且,如果要处理非常大的数字,则可能需要将它们表示为数字列表,并编写自己的算术函数以在它们计算结果并将它们输出到其他流时在它们上进行流式处理。
clojure.math.numeric-tower
以前使用clojure.contrib.math
。
(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))
clojure.contrib.genric.math函数如何
clojure.contrib.generic.math-functions库中有一个pow函数。它只是Math.pow的宏,更像是一种调用Java数学函数的“ clojureish”方式。