Clojureでべき乗を実行するにはどうすればよいですか?現時点では、整数の累乗のみが必要ですが、問題は分数にも当てはまります。
Clojureでべき乗を実行するにはどうすればよいですか?現時点では、整数の累乗のみが必要ですが、問題は分数にも当てはまります。
回答:
古典的な再帰(これを見て、スタックが爆破されます)
(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には、適切に機能するパワー関数があります。Clojureの任意精度の数値型をすべて正しく処理するため、Javaの相互運用機能ではなく、これを使用することをお勧めします。名前空間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
org.clojure.math.numeric-tower
Clojure名前空間にclojure.math.numeric-tower
アクセスできるようにするには、まずJavaパッケージをインストールする必要があります!
コマンドラインで:
$ lein new my-example-project
$ cd lein new my-example-project
次に、依存関係ベクトルを編集project.clj
して追加[org.clojure/math.numeric-tower "0.0.4"]
します。
レイン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
かわかりません。必要なことを実行する単純な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))
reduceを使用した単純なワンライナー:
(defn pow [a b] (reduce * 1 (repeat b a)))
clojure.contrib.genric.math-functionsはどうですか
clojure.contrib.generic.math-functionsライブラリには、pow関数があります。これは、Math.powの単なるマクロであり、Java数学関数を呼び出すためのより「奇妙な」方法です。