Clojure BigInt is not Java BigInteger
bigdecimal, biginteger, clojure
Solution
=> (type (.unscaledValue 1.31M))
java.math.BigInteger
=> (type (biginteger 131))
java.math.BigInteger
=> (BigDecimal. (biginteger 131) 2)
1.31M
Problem
I'm trying to use BigDecimals in Clojure to model (if necessary) arbitrary precision numbers. I have a strange error when I try to instantiate a BigDecimal from an unscaled value and scale factor: ``` user=> 1.31M 1.31M (OK) user=> (class 1.31M) java.math.BigDecimal (OK) user=> (.unscaledValue 1.31M) 131 (OK) user=> (.scale 1.31M) 2 (OK) user=> (.movePointLeft (BigDecimal. 131) 2) 1.31M (OK) user=> (BigDecimal. (BigInteger. "131") 2) 1.31M user=> (BigDecimal. 131N 2) (WRONG!!!) IllegalArgumentException No matching ctor found for class java.math.BigDecimal clojure.lang.Reflector.invokeConstructor (Reflector.java:183) user=> (BigDecimal. (BigInteger. "131") 2) 1.31M ``` The problem here is that the clojure big integer IS NOT a java.math.BigInteger object. Even (bigint x) doesn't work: ``` user=> (doc bigint) ------------------------- clojure.core/bigint ([x]) Coerce to BigInt nil ``` And by the way BigInteger constructor doesn't directly accept numeric values. I know I could also do something like: ``` user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M)) 1.31M ``` My question is: is there a more idiomatic way of directly manage BigInteger objects from Clojure? Or am I stuck to wrap everything in a custom library, like: ``` user=> (defn my-bigint [x] (BigInteger. (.toString x))) #'user/my-bigint user=> (my-bigint 131) 131 user=> (BigDecimal. (my-bigint 131) 2) 1.31M ``` Thanks in advance for the help! UPDATE: I NEED a BigInteger for serialization purposes: my idea is to store a BigDecimal as a byte array and an integer. My problem is that in Clojure, if I want, I cannot pass the result of .unscaledValue back and forth 'cause Clojure doesn't handle BigInteger created from Integers (neither do Java, for what it matters): ``` user=> (BigInteger. 3) IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183) ``` A call to .toString on the number is unuseful for the semantics of serialization (and more error prone). I would like to know if in Clojure there is an idiomatic way to write something like: ``` user=> (bigdec 131N 2) ``` No .movePointLeft (creation of two different objects without benefits), no .toString (I have a number, I stringify it and then create a BigInteger, another number, from it?), no slow and indirect method: just plain BigInteger and scale value. Vinz