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

欢迎!有关如何操作的更多信息,请参阅关于页面。

0
Java 互操作

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

4 答案

0

评论由:alexmiller

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

0

评论人:gshayban

补丁似乎可能会对内联产生负面影响

0

评论由:alexmiller

这确实是一种可能性,尽管我认为在这个案例中可能很少见。

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