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

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

0
Clojure
closed

我在查看clojure.core/abs在类型Ratio上的新实现时,发现代码中的确有一个假设,即使用类型clojure.lang.Ratio的内部详细信息,分母始终是正数(例如,看看类型Ratio的isNeg和isPos方法的定义)。

我开始寻找可能违反该假设的情况,并找到了以下情况,所有这些可能都是表达式具有Long/MIN_VALUE作为分母,以及具有类型Long或更小类型的整数作为分子的Ratio值产生的。

$ clj -Sdeps '{:deps {org.clojure/clojure {:mvn/version "1.11.0-alpha4"}}}'
Clojure 1.11.0-alpha4

user=> (/ 1 Long/MIN_VALUE)
-1/-9223372036854775808
user=> (< (/ 1 Long/MIN_VALUE) 0)         ;; This gives correct numerical answer
true
user=> (< (* 1 (/ 1 Long/MIN_VALUE)) 0)        ;; This does not
false
user=> (abs (/ 1 Long/MIN_VALUE))            ;; Gives incorrect numerical answer
1/-9223372036854775808
user=> (< (abs (/ 1 Long/MIN_VALUE)) 0)        ;; correct numerical answer
false
user=> (< (* 1 (abs (/ 1 Long/MIN_VALUE))) 0)       ;; incorrect numerical answer
true

我仔细检查了Clojure实现源文件Numbers.java中的其他Ratio出现,据我所知,唯一的问题是LongOps类中的divide方法。如果该方法通过检查分子和/或分母是否等于Long/MIN_VALUE的特殊情况并在此情况下有所不同,我没有看到其他错误。

当分子等于Long/MIN_VALUE时,还有一个问题,其根本原因在于同一LongOps divide方法。

user=> (/ Long/MIN_VALUE -3)   ;; should return positive value, but returns negative value
-9223372036854775808/3
user=> (< (/ Long/MIN_VALUE -3) 0)
true
已关闭,注释为:已修复在 Clojure 1.12.0-alpha4 中

2 答案

0
 
最佳答案

已在此处作为https://clojure.atlassian.net/browse/CLJ-2694提交,并添加了一个补丁以检测Long/MIN_VALUE的使用并转而使用bigint实现。添加了这些情况作为测试。

0
我不知道,但是我认为修复其中一个不一定可以修复另一个,即每个问题背后的Java方法是互不相同的,至少今天是这样。
你能澄清一下吗?
嗯,你可能是对的,或者其中一些属于这个WontFix JIRA: https://clojure.atlassian.net/browse/CLJ-1253

似乎有些奇怪,在几乎所有情况下,/ 都会通过Ratio返回一个确切的答案,但上面的测试用例显示,在某些情况下,它甚至在不返回Ratio的情况下也不返回正确的答案。  这不是返回值存储在Long/long中的情况。
这个问题中的测试用例给出的答案是错误的,因为LongOps方法的divide实现有误。  CLJ-1254的根本原因是由于LongOps方法的quotient实现,我相信,所以这些不同部分单独的bug。
...