尝试从 BigDecimal 转换为 long
(long 201608081812113241M) => 201608081812113248 ;; 不是一个真正的数字
让我们直接使用 BigDecimal.longValue()
(.longValue 201608081812113241M) => 201608081812113241 ;; ok, 正确值
查看 clojure.lang.RT 并怀疑转换链不正确
(.doubleValue (.longValue 201608081812113241M)) => 201608081812113248 ;; yes, 不正确
原因: BigDecimal 到 long 的强制类型转换会使用 Number.longValue(),在这种情况下,即使转换是可行的,也会生成一个不正确的值。javadoc 表明这个调用与 double 到 long 的转换等效,并且可能以多种方式造成损失。
方法: 在 long 转换中添加显式的情况以处理 BigDecimal,并调用 longValueExact()。补丁为一些 BigInteger 和 BigDecimal 值添加了额外的强制类型转换测试。unchecked-long 强制类型转换似乎不受影响(返回了未更改的正确值)。
问题: 虽然可能会让人困惑,但错误的可能实际上是与 Java 一致的正确值。unchecked-long 会给出预期的结果,并且可能是这个例子更好的选择。因此,我们可能应该**不应用此补丁**,而是什么都不做。如果我们确实要应用补丁,我们可能还希望将相当于调用 byteValueExact()、shortValueExact()、intValueExact() 和 toBigIntegerExact() 的更改应用到适当的立足点处。
补丁: clj-2001.patch