How to do exponentiation in clojure?
Solution 1
classic recursion (watch this, it blows stack)
(defn exp [x n]
(if (zero? n) 1
(* x (exp x (dec n)))))
tail recursion
(defn exp [x n]
(loop [acc 1 n n]
(if (zero? n) acc
(recur (* x acc) (dec n)))))
functional
(defn exp [x n]
(reduce * (repeat n x)))
sneaky (also blows stack, but not so easily)
(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))))))
library
(require 'clojure.contrib.math)
Solution 2
Clojure has a power function that works well: I'd recommend using this rather than going via Java interop since it handles all the Clojure arbitrary-precision number types correctly. It is in namespace clojure.math.numeric-tower.
It's called expt
for exponentiation rather than power
or pow
which maybe explains why it's a bit hard to find ... anyway here's a small example (note that use
works but better 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
Reminder about package installation
You must first install the Java package org.clojure.math.numeric-tower
to make the Clojure namespace clojure.math.numeric-tower
accessible!
On the command line:
$ lein new my-example-project
$ cd lein new my-example-project
Then edit project.clj
and add [org.clojure/math.numeric-tower "0.0.4"]
to the dependencies vector.
Start a lein REPL (not a clojure REPL)
$ lein repl
Now:
(require '[clojure.math.numeric-tower :as math])
(math/expt 4 2)
;=> 16
or
(require '[clojure.math.numeric-tower :as math :refer [expt]])
(expt 4 2)
;=> 16
Solution 3
You can use java's Math.pow
or BigInteger.pow
methods:
(Math/pow base exponent)
(.pow (bigdec base) exponent)
Solution 4
When this question was originally asked, clojure.contrib.math/expt was the official library function to do this. Since then, it has moved to clojure.math.numeric-tower
Solution 5
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
Peter
SOreadytohelp Make everything as simple as possible.. (but not simpler!) Albert Einstein The irrationality of a thing is no argument against its existence, rather a condition of it. Friedrich Nietzsche
Updated on October 29, 2021Comments
-
Peter over 2 years
How can I do exponentiation in clojure? For now I'm only needing integer exponentiation, but the question goes for fractions too.
-
Peter about 13 years+1, though I know you can interop with java libs; however, 1) Math.pow works with doubles, I need Integers, can you give an example? 2) Do you really have to use interop for sth. simple as powers?
-
DaVinci about 13 yearsClojure is built arround the java libraries, it does not attempt to fix what is not broken and Math/pow works just fine. Why do you need to care for doubles or integers? You could also use this richhickey.github.com/clojure-contrib/…
-
sepp2k about 13 years@Peter: 1) Unless your powers are so large that they can't be accurately represented by doubles anymore, there really is no problem with just casting the result to int. 2) I don't see how writing
Math/pow
is more complicated thanmath-pow
or whatever the name would be if there was a clojure equivalent. If there already is a simple java method that does what you want, there is no reason to recreate the functionality in clojure. Java interop is not inherently harmful. -
Peter about 13 years@Da vinci : strange remark, it's a language of it's own, and has a lot of functions that are in Java (like stringreverse)
-
Peter about 13 years@sepp : It is indeed about big nummers (project euler like stuff)
-
sepp2k about 13 years@Peter: For bigints you can use java's BigInteger.pow instance method.
-
mikera about 13 years+1 for this answer since it handles all the Clojure exact (i.e. BigDecimal / BigInteger) arithmetic correctly.
-
mikera about 13 yearsI think you are better using Clojure's clojure.contrib.math/expt if you want accurate biginteger powers. Probably does the same under the hood but much nicer than going via Java interop.....
-
TJ Trapp over 12 yearsbut seems to max out at 2^63... def not capable of 2^200
-
user1568901 over 12 yearsProbably unknown because it doesn't appear to be part of standard Clojure. 1.3.0 tosses errors about not being able to locate the math.clj when I try to do it this way.
-
mikera over 12 yearsI think it's now in "clojure.math.numeric-tower" as of 1.3 (since clojure.contrib got broken up into individual libraries)
-
noisesmith over 10 yearsalso you can use the literal notation for this:
(.pow 2M 100)
-
KIM Taegyoon over 10 yearsTheir types are different. user=> (type 2M) java.math.BigDecimal user=> (type (BigInteger. "2")) java.math.BigInteger
-
Karl Rosaen about 10 yearssee fully iterative version of sneaky solution below stackoverflow.com/a/22977674/231589
-
Brad Koch almost 10 years"Note - the contrib libs have moved to individual repos under Clojure org"; this link only answer is now misleading.
-
Brad Koch almost 10 years"Note - the contrib libs have moved to individual repos under Clojure org"; this answer is outdated.
-
Daniel Gruszczyk almost 10 yearsimo best solution, showr, using existing libraries, and including handling of bigint. +1
-
Zaz over 8 yearsFor me
(Math/pow Math/E x)
does the trick (replacingMath/E
with the base of your choice). -
alvaro g about 8 yearsClojure.contrib.math is now deprecated, see Math.Numeric-Tower
-
Pointo Senshi over 7 yearsThe second suggestion (tail recursive) has integer overflow for n < 0.
-
Daniel Szmulewicz over 7 yearsFantastic answer. Here's how to do with it with a macro: (defmacro exp [x n] `(* ~@(take n (repeat x))))
-
loxaxs about 6 yearsTerminal recursion for the fast exponentiation algorithm:
(def exp (letfn [(rexp [x n r] (cond (zero? n) r (even? n) (recur (*' x x) (/ n 2) r) :else (recur (*' x x) (/ (dec n) 2) (*' x r))))] (fn [x n] (rexp x n 1))))
. It never blows the stack. Test(exp 1 (exp 2 30000))
-
johncip almost 5 yearsI'm getting
No matching method pow ... for class clojure.lang.BigInt
-- shouldn't it be(.pow (biginteger base) exponent)
? -
Andrew Koster over 4 yearsNone of the answers that involve importing an existing function work (including the
(require 'clojure.contrib.math)
in this answer). But(defn exp [x n] (reduce * (repeat n x)))
works great, and is easy to understand! -
David Tonhofer about 4 yearsClojure has no "tail recursion" (or rather, "tail-call optimization") because Java does have it. A loop, however, is a loop.
-
David Tonhofer about 4 yearsAdded "reminder about package installation" to allay user frustration.