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

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

0
Clojure
已关闭

我查看了Clojure implementation中关于Ratio类型的新clojure.core/abs实现,代码中似乎存在假定,使用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

我认为这已包含在 https://clojure.atlassian.net/browse/CLJ-1254

我不太清楚,但我想修复一个不一定能修复另一个,即每个问题的底层 Java 方法是相互独立的,至少到目前为止是这样的。
你能澄清一下吗?
嗯,也许你是对的,而且/在几乎所有情况下都通过Ratio返回精确答案,但在上面的测试用例中显示,在某种情况下它不返回正确的答案,即使它返回了Ratio。 这些不是返回值存储在Long/long中的情况。

它似乎有一点奇怪,/在几乎所有情况下都通过Ratio返回精确答案,但上面的测试用例显示,在某些情况下,它甚至不返回正确的答案,即使是Ratio。 这不是返回值存储在Long/long中的情况。
by
这个问题中的测试用例返回错误答案是因为LongOps方法的除法实现方式。我相信,CLJ-1254的根本原因是因为LongOps方法的做法,这是我在不同的实现部分独立的bug。
...