web-dev-qa-db-ja.com

clojureでべき乗を行う方法は?

Clojureで累乗を行うにはどうすればよいですか?今のところ、私は整数の累乗だけを必要としていますが、問題は分数にも当てはまります。

96
Peter

古典的な再帰(これを見て、スタックを爆破する)

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

Clojureには、うまく機能するべき乗関数があります。すべてのClojureの任意精度の数値型を正しく処理するため、Java interopを経由するのではなく、これを使用することをお勧めします。

exptpowerではなく、exponentiationの場合はpowと呼ばれます。 :

(use 'clojure.math.numeric-tower)  ; as of Clojure 1.3
;; (use 'clojure.contrib.math)     ; before Clojure 1.3

(expt 2 200)
=> 1606938044258990275541962092341162602522202993782792835301376
75
mikera

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

(Math/pow base exponent)

(.pow (bigint base) exponent)
52
sepp2k

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

11
amalloy
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
7
KIM Taegyoon

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

 (defn pow [b e] (Math/pow b e))

そして、この関数では、intまたは同様のものにキャストできます。関数はパラメーターよりも別の関数に渡すことができるため、メソッドよりも便利です。この場合、mapが思い浮かびます。

Java interopを回避する必要がある場合は、独自のべき関数を作成できます。たとえば、これは単純な関数です。

 (defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
   (if (neg? p) (/ 1 result) result)))

これは、整数指数(つまり、根がない)のべき乗を計算します。

また、large数を扱う場合は、BigIntegerの代わりにintを使用することもできます。

非常に大きい数を扱う場合は、それらを数字のリストとして表現し、独自の算術関数を記述して結果を計算し、結果を他の人に出力するストリーム。

5
Goran Jovic

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

(defn expt [x pow] (apply * (repeat pow x)))
4
TJ Trapp

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)))
3
Karl Rosaen

つかいます - 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))
2
micrub

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

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

Reduceを使用したシンプルなワンライナー:

(defn pow [a b] (reduce * 1 (repeat b a)))
2
Alan R. Soares

試して

(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)ソリューションの場合、自分で実装する場合(正の整数のみをサポート)。明らかに、より良い解決策は、他の人が指摘したライブラリ関数を使用することです。

1
Retief

Clojure.contrib.genric.math-functionsはどうですか

Clojure.contrib.generic.math-functionsライブラリにはpow関数があります。これはMath.powの単なるマクロであり、Java math関数を呼び出す「clojureish」な方法です。

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

0
fido