10
votes

Is there way to perform arbitrary precision exponentiation in Clojure? I've tried Math/pow and the expt function from clojure.math.numeric-tower, but both will only return limited precision. For example:

(with-precision 100 (expt 2 1/2))
=> 1.4142135623730951

How do I get more digits?

2
How many digits do you want? sqrt(2) can't be expressed as a rational number (as a fraction of two finite numbers). Do you want a lazy list of digits? - Dmytro Sirenko
I tried to get 100 digits by using "with-precision", but as you can see that did nothing. The answer is: I want to specify the precision. The expt function accepts bigdec arguments but only returns limited precision results. - Lee Phillips

2 Answers

4
votes

Apfloat for Java provides fast arbitrary precision arithmetic. You can easily use it by adding the following dependency information to your project.clj file, if your project comes with Leiningen.

[org.apfloat/apfloat "1.6.3"]

You can perform arbitrary precision exponentiation in Clojure using Apfloat. For example:

user> (import '(org.apfloat Apfloat ApfloatMath))
org.apfloat.ApfloatMath

user> (-> (Apfloat. 2M 100) (ApfloatMath/pow (Apfloat. 0.5M 100)))
1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727
2
votes

math/expt is likely not the function you are looking for as it returns a double instead of a BigDecimal in this context, and hence ignores your with-precision statement:

Returns an exact number if the base is an exact number and the power is an integer, otherwise returns a double.

user> (type (with-precision 100 (math/expt 2M 1/2)))
java.lang.Double

the answer to this question seems to cover how to get arbitrary precision out of BigDecimal exponentiation. BigDecimal seems not to provide this "out of the box"