我正在尝试在Clojure中使用BigDecimals来建模(如果需要)任意精度数字。 当我尝试从未缩放的值和比例因子实例化BigDecimal时,我有一个奇怪的错误:
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
这里的问题是clojure大整数不是java.math.BigInteger对象。 Even(bigint x)不起作用:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
顺便说一句BigInteger构造函数不直接接受数值。我知道我也可以这样做:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
我的问题是:是否有更惯用的方法直接管理Clojure中的BigInteger对象?或者我坚持将所有内容都包装在自定义库中,例如:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
提前感谢您的帮助!
更新:我需要 BigInteger用于序列化目的:我的想法是将BigDecimal存储为字节数组和整数。我的问题是在Clojure中,如果我想要,我不能来回传递.unscaledValue的结果'因为Clojure不处理从Integers创建的BigInteger(Java也没有,因为它重要):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
对数字的.toString调用对于序列化的语义是不可用的(并且更容易出错)。我想知道在Clojure中是否有一种惯用的方法可以写出类似的东西:
user=> (bigdec 131N 2)
没有.movePointLeft(创建两个没有好处的不同对象),没有.toString(我有一个数字,我将其字符串化,然后创建一个BigInteger,另一个数字,来自它?),没有慢速和间接方法:只是简单BigInteger和规模值。
Vinz
答案 0 :(得分:8)
=> (type (.unscaledValue 1.31M))
java.math.BigInteger
=> (type (biginteger 131))
java.math.BigInteger
=> (BigDecimal. (biginteger 131) 2)
1.31M
答案 1 :(得分:4)
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)))
答案 2 :(得分:0)
我更喜欢这个:
(-> 131M (.movePointLeft 2))