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)))
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