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实现中source file 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

我认为这已经在 https://clojure.atlassian.net/browse/CLJ-1254 中涵盖了。

我暂时不清楚,但我觉得修复一个不一定能修复另一个,即每个问题的底层 Java 方法是分开的,至少目前是这样。
你能澄清一下吗?
嗯嗯,也许你是对的,或者其中一些可能属于这个WontFix JIRA:https://clojure.atlassian.net/browse/CLJ-1253

看起来在几乎所有情况下,/都返回精确答案,通过Ratio来实现,但上述测试用例显示,在某些情况下,即使在返回Ratio时,它也不会返回正确答案。  这不是返回值存储在Long/long中的情况。
这个问题的测试用例给出了错误答案,是因为LongOps方法除法的实现方式。  CLJ-1254的根本原因我相信是因为LongOps方法除法的实现方式,这是我所能看到的独立于不同实现的bug。
...