如何在 Clojure 中进行求幂?

发布于 2024-10-18 09:40:08 字数 47 浏览 3 评论 0原文

如何在 Clojure 中进行求幂? 现在我只需要整数求幂,但问题也适用于分数。

How can I do exponentiation in clojure?
For now I'm only needing integer exponentiation, but the question goes for fractions too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

纵山崖 2024-10-25 09:40:08

经典递归(看这个,它会破坏堆栈)

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

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)
┊风居住的梦幻卍 2024-10-25 09:40:08

Clojure 有一个运行良好的强大函数:我建议使用它而不是通过 Java 互操作,因为它可以正确处理所有 Clojure 任意精度数字类型。它位于命名空间 clojure.math.numeric-tower 中。

它被称为expt用于指数而不是powerpow这也许解释了为什么它有点难找到..无论如何,这是一个小例子(请注意 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

Clojure has a power function that works well: I'd recommend using this rather than going via Java interop since it handles all the Clojure arbitrary-precision number types correctly. It is in namespace clojure.math.numeric-tower.

It's called expt for exponentiation rather than power or pow which maybe explains why it's a bit hard to find ... anyway here's a small example (note that use works but better 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

Reminder about package installation

You must first install the Java package org.clojure.math.numeric-tower to make the Clojure namespace clojure.math.numeric-tower accessible!

On the command line:

$ lein new my-example-project
$ cd lein new my-example-project

Then edit project.clj and add [org.clojure/math.numeric-tower "0.0.4"] to the dependencies vector.

Start a lein REPL (not a clojure REPL)

$ lein repl

Now:

(require '[clojure.math.numeric-tower :as math])
(math/expt 4 2)
;=> 16

or

(require '[clojure.math.numeric-tower :as math :refer [expt]])
(expt 4 2)
;=> 16
番薯 2024-10-25 09:40:08

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

(Math/pow base exponent)

(.pow (bigdec base) exponent)

You can use java's Math.pow or BigInteger.pow methods:

(Math/pow base exponent)

(.pow (bigdec base) exponent)
妞丶爷亲个 2024-10-25 09:40:08

当这个问题最初被问到时, clojure.contrib .math/expt 是执行此操作的官方库函数。从那时起,它已移至 clojure.math.numeric-tower

When this question was originally asked, clojure.contrib.math/expt was the official library function to do this. Since then, it has moved to clojure.math.numeric-tower

恍梦境° 2024-10-25 09:40:08
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
怪我入戏太深 2024-10-25 09:40:08

从 Clojure 1.11 开始,clojure.math/pow 附带 标准库,适用于 Clojure 和 ClojureScript。

Since Clojure 1.11, clojure.math/pow ships with the standard library, and works both for Clojure and ClojureScript.

此岸叶落 2024-10-25 09:40:08

如果您确实需要一个函数而不是方法,您可以简单地包装它:

 (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

如果您正在处理非常大的数字,您可能希望将它们表示为数字列表,并编写自己的算术函数来在它们计算结果并将结果输出到其他某个时对它们进行流处理溪流。

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.

屋顶上的小猫咪 2024-10-25 09:40:08

我认为这也可行:

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

I think this would work too:

(defn expt [x pow] (apply * (repeat pow x)))
七堇年 2024-10-25 09:40:08

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

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

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)))
四叶草在未来唯美盛开 2024-10-25 09:40:08

使用尾递归和支持负指数的“偷偷摸摸”方法的实现:

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

Implementation of "sneaky" method with tail recursion and supporting negative exponent:

(defn exp
  "exponent of x^n (int n only), with tail recursion and O(logn)"
   [x n]
   (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)))))))
无需解释 2024-10-25 09:40:08

使用reduce 的简单单行:

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

A simple one-liner using reduce:

(defn pow [a b] (reduce * 1 (repeat b a)))
心作怪 2024-10-25 09:40:08

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

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))
淡忘如思 2024-10-25 09:40:08

请尝试

(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) 解决方案(仅支持正整数)。显然,更好的解决方案是使用其他人指出的库函数。

Try

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

for a tail-recursive O(log n) solution, if you want to implement it yourself (only supports positive integers). Obviously, the better solution is to use the library functions that others have pointed out.

静谧幽蓝 2024-10-25 09:40:08

我个人使用:

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

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

适用于所有大小的整数。

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

I personally use:

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

Notice the apostrophe (') after the asterisk.

Works well for all sizes of integers.

Note: This might be a little slow for some implementations.
(time (pow 2 200000)) took 1.2 seconds to resolve on my system.

谁的新欢旧爱 2024-10-25 09:40:08

clojure.contrib.genric.math-functions 怎么样

clojure.contrib.generic.math-functions 库中有一个 pow 函数。它只是 Math.pow 的一个宏,更多的是调用 Java 数学函数的“clojureish”方式。

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

How about clojure.contrib.genric.math-functions

There is a pow function in the clojure.contrib.generic.math-functions library. It is just a macro to Math.pow and is more of a "clojureish" way of calling the Java math function.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文