Re: bigint and biginteger
Thank you, Mark and Mike Awesome explanation and examples Plínio On Sat, Jun 7, 2014 at 8:46 AM, Mike Fikes mikefi...@me.com wrote: Thanks for the historical perspective, puzzler! In addition to performance considerations, Clojure Programming points to an inconsistency between hash codes for longs and BigIntegers as a motivation. Using the example number from that excellent book on Clojure 1.5.1 (on Java 8, FWIW), I can cause this: #{6948736584 (biginteger 6948736584)} ; = #{6948736584 6948736584} #{6948736584 (bigint 6948736584)} ; = IllegalArgumentException Duplicate key: 6948736584 clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56) (System/getProperty java.version) ; = 1.8.0_05 (clojure-version) ; = 1.5.1 On Clojure 1.6, thankfully both fail, even in the face of the inconsistency between .hashCode implementations. If that essentially addresses the 2nd rationale for introducing a special BigInt class, maybe with both things being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the sole arbitrary precision representation of ℤ. -- 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.
Re: bigint and biginteger
Thanks for the historical perspective, puzzler! In addition to performance considerations, *Clojure Programming* points to an inconsistency between hash codes for longs and BigIntegers as a motivation. Using the example number from that excellent book on Clojure 1.5.1 (on Java 8, FWIW), I can cause this: #{6948736584 (biginteger 6948736584)} ; = #{6948736584 6948736584} #{6948736584 (bigint 6948736584)} ; = IllegalArgumentException Duplicate key: 6948736584 clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56) (System/getProperty java.version) ; = 1.8.0_05 (clojure-version) ; = 1.5.1 On Clojure 1.6, thankfully both fail, even in the face of the inconsistency between .hashCode implementations. If that essentially addresses the 2nd rationale for introducing a special BigInt class, maybe with both things being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the sole arbitrary precision representation of ℤ. -- 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.
bigint and biginteger
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.
Re: bigint and biginteger
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 pbaldu...@gmail.com 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.