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

欢迎!请参阅关于页面以了解更多关于其工作方式的信息。

0
Clojure
已关闭

我在查看新的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的特殊情况并对此进行一些不同处理来解决这个问题,我看不出其他任何bug。

如果分子等于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

在大多数情况下,'/' 返回一个精确的答案,这似乎有点奇怪,但上面提到的测试用例显示,在某些情况下,它甚至不会返回正确的答案,即使它返回一个比率。这些并不是返回值被存储在Long/long中的情况。
这个问询中的测试用例给出错误答案是因为LongOps方法的除法实现方式。我相信CLJ-1254的根本原因是因为LongOps方法的商数实现方式,据我所知,这些独立的缺陷是隐藏在实现的不同部分中的。
...