Clojure BigInt is not a Java BigInteger

I am trying to use BigDecimals in Clojure to model (if necessary) arbitrary precision numbers. I have a weird error when I try to instantiate a BigDecimal from an unscaled value and a 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 is that a large number of Clojure is NOT a java.math.BigInteger object. Even (bigint x) does not work:

 user=> (doc bigint) ------------------------- clojure.core/bigint ([x]) Coerce to BigInt nil 

And by the way, the BigInteger constructor does not directly accept numerical values. I know that I could do something like:

 user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M)) 1.31M 

My question is: is there a more idiomatic way to directly manipulate BigInteger objects from Clojure? Or I am stuck to wrap everything in a user library, for example:

 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 your help!

UPDATE: I NEED BigInteger for serialization purposes: my idea is to store BigDecimal as an array of bytes and an integer. My problem is that in Clojure, if I want, I cannot pass the result .unscaledValue back and forth, because Clojure does not process BigInteger created from integers (also not Java, for which this is important):

 user=> (BigInteger. 3) IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183) 

Calling .toString for a number is not used for serialization semantics (and more error-prone ones). I would like to know if Clojure has an idiomatic way to write something like:

 user=> (bigdec 131N 2) 

No .movePointLeft (creating two different objects without advantages), no .toString (I have a number, I build it and then create BigInteger from it, another number?), Not a slow and indirect method: just BigInteger value and scale.

Vinz

+7
source share
3 answers
 => (type (.unscaledValue 1.31M)) java.math.BigInteger => (type (biginteger 131)) java.math.BigInteger => (BigDecimal. (biginteger 131) 2) 1.31M 
+8
source
 user=> (.movePointLeft (bigdec 131) 2) 1.31M user=> (.movePointLeft (bigdec 131N) 2) 1.31M user=> (source bigdec) (defn bigdec "Coerce to BigDecimal" {:tag BigDecimal :added "1.0" :static true} [x] (cond (decimal? x) x (float? x) (. BigDecimal valueOf (double x)) (ratio? x) (/ (BigDecimal. (.numerator x)) (.denominator x)) (instance? BigInteger x) (BigDecimal. ^BigInteger x) (number? x) (BigDecimal/valueOf (long x)) :else (BigDecimal. x))) 
+4
source

I like it a little better:

 (-> 131M (.movePointLeft 2)) 
0
source

All Articles