如何在Clojure中进行指数运算?

131

我该如何在Clojure中进行指数运算?目前我只需要整数指数,但这个问题也适用于分数。


28
作为一个不了解Clojure语言的人,但是因为喜欢Lisp语言、函数式编程和众多实用库而有倾向性,我很失望这个简单的问题有这么多答案,或者说需要被问到。我本以为指数运算会是一种基本的函数,不需要进行任何特殊处理。不过,我还是很高兴这个问题被问出来了。 - Mars
2
嗯,可能某个版本应该在核心中。但我认为许多答案仍然是一个好迹象。“多种实现路径”似乎是许多这些功能未提供的原因——用户应该知道他们正在使用的函数的细节,以提高效率。例如(正如所选择的答案中指出的那样),有些方法可能会潜在地使堆栈溢出,而其他方法则不太可能。也许有些是懒惰的,有些是急切的……所有这些细节都需要在Clojure中付出一些注意力,这就是为什么我认为大多数非平凡库由于哲学原因而未提供的原因。 - jm0
4
在Clojure核心中没有仅限于指数函数的原因是,出于效率考虑,Clojure的数值体系存在严重问题。因此,指数运算可能有各种不同的含义。例如,(exp 2 (exp 2 200)) 应该是一个错误还是需要花费很长时间才能计算出来的巨大整数?如果只想要通常的浮点数指数运算,则可以使用Java内置的函数。如果希望使用像实数一样的数字,不惜代价,可以使用Scheme而不是Clojure。 - John Lawrence Aspden
15个回答

3

使用 reduce 的简单一行代码:

(defn pow [a b] (reduce * 1 (repeat b a)))

2

使用 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))

1

我个人使用:

(defn pow [x n] (reduce *' (repeat n x)))

注意星号后面的撇号(')。

适用于所有大小的整数。

注意:对于某些实现来说,这可能有点慢。 (time (pow 2 200000))在我的系统上解决需要1.2秒。


1

尝试

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

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


0

1
注意 - contrib libs已经移动到Clojure组织下的各个仓库中。这个回答已经过时了。 - Brad Koch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接