尝试将 BigDecimal 转换为 long
(long 201608081812113241M) => 201608081812113248 ;; 这并不是我们的数字
直接使用 BigDecimal.longValue()
(.longValue 201608081812113241M) => 201608081812113241 ;;好了,正确的值
检查 clojure.lang.RT 并怀疑不正确的转换链路
(.longValue (.doubleValue 201608081812113241M)) => 201608081812113248 ;; 是的,不正确
原因:BigDecimal 到 long 的强制类型转换将使用 Number.longValue(),在这种情况下会产生不正确的值,尽管转换是可能的。Javadoc 表示此调用相当于 double 到 long 的转换,并且可能在几个方面导致数据丢失。
方法:在长强制类型转换中添加显式情况以处理 BigDecimal,并且调用 longValueExact()。修复补丁为某些 BigInteger 和 BigDecimal 值添加了额外的强制类型转换测试。未检查的长强制类型转换似乎没有受到影响(返回了正确的值,没有更改)。
问题:虽然可能会令人困惑,但错误的结果实际上可能是与 Java 一致的。unchecked-long 将给出预期的结果,可能是本例中更好的选择。因此,我们可能应该不应用此修复,而什么也不做。如果我们继续应用修复,我们可能还想在适当的位置也应用一个等效的更改,以调用 byteValueExact()、shortValueExact()、intValueExact() 和 toBigIntegerExact()。
修复补丁:clj-2001.patch