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

欢迎!请参见关于页面了解更多关于如何使用此功能的信息。

0
Clojure
已关闭

我在查看 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
我不知道具体情况,但我认为修复一个不一定能修复另一个,即每个问题背后的问题方法是不同的,至少现在是这样的。
请澄清一下?
Hmmm,或许你是对的,也许这其中的某些问题属于这个WontFix JIRA: https://clojure.atlassian.net/browse/CLJ-1253

看起来很奇怪,几乎在所有情况下,斜杠符号返回的确实是精确的Ratio值,但上述测试案例表明,在某些情况下,它并不返回正确的答案,即使它返回了Ratio值。这些情况并未在Long/long类型的返回值中存储。
这个问题中的测试案例给出错误答案,因为LongOps方法的除法实现方式问题。我认为CLJ-1254的根本原因也是由于LongOps方法的除法实现方式问题,所以它们是实施不同部分中的独立错误。
...