Java has a class called java.math.BigInteger. Clojure's biginteger simply
typecasts to the built-in java class.
Several years ago, Clojure exclusively used java.math.BigInteger to handle
integers larger than longs. Back then, Clojure's arithmetic operators
would automatically overflow, so if you added to longs and the sum was
larger than a long, you'd get back a BigInteger.
Then, Clojure changed so that arithmetic overflows would throw an error
rather than automatically "promoting" to BigInteger. Users who wanted
overflow were given two options:
Option 1: Use auto-promoting arithmetic operators (e.g., +' and *').
Option 2: Seed your arithmetic with a BigInteger so that all the arithmetic
would be "contaminated" by the BigInteger, and all the numbers would be
cast into BigIntegers before the arithmetic happened.
So, for example, if you wrote a loop-recur version of summing all the
numbers from 1 to n:
(defn sum [n]
(loop [acc 0
n n]
(if (zero? n) acc (recur (+ acc n) (dec n)
This could theoretically overflow for extremely large values of n, so if
you want to handle that, choice 1 is:
(defn sum [n]
(loop [acc 0
n n]
(if (zero? n) acc (recur (+' acc n) (dec n)
Choice 2 is:
(defn sum [n]
(loop [acc (biginteger 0)
n n]
(if (zero? n) acc (recur (+ acc n) (dec n)
What happened is that people who made choice #2 started complaining of
performing problems. Turned out that if you converted everything to
bigintegers, but most of your numbers were actually in the long range, you
were paying a pretty significant performance penalty.
So, the Clojure group decided to make a faster BigInteger, which they
called BigInt, and numbers like 0N are just shorthand for (bigint 0).
Basically, as long as your BigInt falls within long range, internally it is
stored and manipulated as a long. This minimizes the performance penalty
for using BigInts with numbers that can be represented as longs. The
penalty is fairly comparable to the penalty of using boxed Longs versus
primitive longs. Only if you go outside of that range do you start paying
the performance for the more complex BigInteger representation.
You can see
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/BigInt.java
for the source code of how BigInt is represented as a long if it can, and
otherwise a BigInteger.
The main downside of this is that BigInt lacks the richness of the
java.math.BigInteger API. I think at one time there was a plan to make
BigInt support the exact same API as java.math.BigInteger, but it never
happened. So, you need to explicitly convert to BigInteger if you want to
use those methods.
Interestingly, I just tried to type up a few functions to demonstrate the
slowness of java.math.BigInteger versus boxed Longs for numbers that fall
within the long range, and I couldn't come up with any example that showed
a significant difference.
This makes me wonder:
*Is it possible that Java 8 made performance improvements to
java.math.BigInteger that render clojure.lang.BigInt obsolete?*
If so, that would be wonderful -- Clojure could go back to just using the
BigInteger class and we'd get both good performance and the richer API.
On Fri, Jun 6, 2014 at 6:06 PM, Plínio Balduino wrote:
> Hi there.
>
> I read old threads and I didn't understand why Clojure has bigint and
> biginteger.
>
> Could you explain better?
>
> Thank you
>
> Plínio
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.