2024 Clojure 状态调查!中分享您的想法。

欢迎!请查看关于页面以了解更多关于此的工作方式信息。

0 投票
Java 互操作

尝试将 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

4 答案

0 投票

评论由:alexmiller 添加

是的,RT.longCast() 似乎没有明确处理 BigDecimal。

0 投票

评论者:gshayban

看起来这个补丁可能会对内联产生负面影响

0 投票

评论由:alexmiller 添加

的确,这是有可能的,尽管我认为在这个情况下这种情况可能很少。

0 投票
参考: https://clojure.atlassian.net/browse/CLJ-2001 (由 alex+import 报告)
...