13 ответов:
классическая рекурсия (смотрите это, он дует стек)
(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 имеет функцию питания, которая работает хорошо: я бы рекомендовал использовать это, а не идти через Java interop, так как он обрабатывает все типы чисел произвольной точности Clojure правильно.
Это называется
exptна возведение в степень, а неpowerилиpowчто, вероятно, объясняет, почему это немного трудно найти..... в любом случае, вот небольшой пример:(use 'clojure.contrib.math) (expt 2 200) => 1606938044258990275541962092341162602522202993782792835301376начиная с Clojure 1.3, эта функция и другие связанные с ней математические функции переместились, поэтому вы нужно сделать:
(use 'clojure.math.numeric-tower)
вы можете использовать java
Math.powилиBigInteger.powметоды:(Math/pow base exponent) (.pow (bigint base) exponent)
когда этот вопрос был первоначально задан,http://clojure.github.com/clojure-contrib/math-api.html#clojure.contrib.math/expt где официальная библиотечная функция для этого жила. С тех пор он переехал в https://github.com/clojure/math.numeric-tower/blob/master/src/main/clojure/clojure/math/numeric_tower.clj#L80
user=> (.pow (BigInteger. "2") 10) 1024 user=> (.pow (BigInteger. "2") 100) 1267650600228229401496703205376
Если вам действительно нужна функция, а не метод, вы можете просто оберните его:
(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.и если вы имеете дело с очень большие числа, вы можете выразить их в виде списков цифр и написать свои собственные арифметические функции для потока над ними, когда они вычисляют результат и выводят результат в какой-то другой поток.
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)))
использовать
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))
попробовать
(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), если вы хотите реализовать его самостоятельно (поддерживает только положительные целые числа). Очевидно, что лучшим решением является использование библиотечных функций, которые указали другие.
реализация "подлого" метода с хвостовой рекурсией и поддержкой отрицательного показателя:
(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)))))))
Как насчет clojure.ВНО.genric.математика-функции
в clojure есть функция pow.ВНО.родовой.библиотека математических функций. Это просто макрос для математики.pow и является скорее "clojureish" способом вызова математической функции Java.
Comments