123

どうすればclojureでべき乗を行うことができますか?今のところ、必要なのは整数のべき乗だけですが、問題は分数にも当てはまります。

4

14 に答える 14

153

古典的な再帰(これを見て、スタックを吹き飛ばします)

(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)
于 2011-02-20T17:07:02.250 に答える
82

Clojureには、うまく機能するべき関数があります。Clojureの任意精度の数値タイプをすべて正しく処理するため、Java相互運用機能を経由するのではなく、これを使用することをお勧めします。名前空間clojure.math.numeric-towerにあります。

べき乗ではなくexptべき乗が求められます。これは、見つけるのが少し難しい理由を説明している可能性があります...とにかくここに小さな例があります(機能しますが、より適切に使用することに注意してpowerください):powuserequire

(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
于 2011-02-22T13:13:18.187 に答える
69

JavaMath.powまたはBigInteger.powメソッドを使用できます。

(Math/pow base exponent)

(.pow (bigdec base) exponent)
于 2011-02-20T12:38:22.093 に答える
14

この質問が最初に行われたとき、clojure.contrib.math/exptはこれを行うための公式のライブラリ関数でした。それ以来、clojure.math.numeric-towerに移動しました

于 2011-02-20T17:00:30.417 に答える
9
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
于 2013-10-27T13:54:21.413 に答える
6

メソッドではなく関数が本当に必要な場合は、単純にラップできます。

 (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

また、非常に大きな数を扱う場合は、それらを数字のリストとして表現し、結果を計算して他のストリームに出力するときに、それらを介してストリーミングする独自の算術関数を作成することをお勧めします。

于 2011-02-20T14:00:46.907 に答える
4

これもうまくいくと思います:

(defn expt [x pow] (apply * (repeat pow x)))
于 2011-10-12T07:29:34.417 に答える
4

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)))
于 2014-04-10T02:36:20.373 に答える
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))
于 2015-07-30T18:03:24.020 に答える
2

末尾再帰を使用し、負の指数をサポートする「卑劣な」メソッドの実装:

(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)))))))
于 2016-02-06T13:53:00.427 に答える
2

reduceを使用した単純なワンライナー:

(defn pow [a b] (reduce * 1 (repeat b a)))
于 2016-04-11T11:41:18.543 に答える
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)ソリューションの場合、自分で実装する場合(正の整数のみをサポート)。明らかに、より良い解決策は、他の人が指摘しているライブラリ関数を使用することです。

于 2012-02-29T22:21:44.233 に答える
1

私は個人的に使用します:

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

アスタリスクの後のアポストロフィ(')に注意してください。

すべてのサイズの整数に適しています。

注:これは、一部の実装では少し遅い場合があります。(時間(pow 2 200000))システムで解決するのに1.2秒かかりました。

于 2021-10-28T22:07:32.133 に答える
0

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

于 2011-02-20T14:03:11.517 に答える