我正在尝试在 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 对象。即使 (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 和缩放价值。
文兹