Как сделать возведение в степень в clojure?
Как я могу сделать возведение в степень в clojure? Пока мне нужно только целочисленное возведение в степень,но вопрос касается и дробей.
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.