尝试从 BigDecimal 转换到 long
(long 201608081812113241M) => 201608081812113248 ;; 实际并非我们的数字
我们只需使用 BigDecimal.longValue()
(.longValue 201608081812113241M) => 201608081812113241 ;; 好了,是正确的值
在 clojure.lang.RT 中进行调查,怀疑转换链不正确
(.longValue (.doubleValue 201608081812113241M)) => 201608081812113248 ;; 是的,不正确
原因: BigDecimal 到 long 的类型转换将使用 Number.longValue(),在这种情况下,尽管转换是可能的,但产生的值不正确。javadoc 指出,该调用相当于 double 到 long 的转换,并且可能在几个方面可能丢失数据。
方法: 在 long 转换中添加显式情况来处理 BigDecimal,并替换为 longValueExact()。补丁增加了对一些 BigInteger 和 BigDecimal 值的额外类型转换测试。未检查的长类型转换似乎不受影响(返回的值没有变化)。
问题: 尽管可能令人困惑,但错误的结果可能实际上是与 Java 一致的。未经检查的长类型转换将给出预期的结果,并且可能是这里的更好选择。所以,我们可能不应该应用此补丁,而应什么都不做。如果我们继续应用补丁,我们可能还可以将等效更改应用到调用 byteValueExact(),shortValueExact(),intValueExact() 和 toBigIntegerExact() 的适当位置。
补丁: clj-2001.patch