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

欢迎!请参阅关于页面了解有关这个工作的更多信息。

0
Java 互操作

对 clojure.core// 的一元调用与二进制调用对除数 0.0 的处理不同,这可能是由于内联引起的。

(/ 0.0) ;; java.lang.ArithmeticException: Divide by zero (/ 1 0.0) ;;= Infinity (/ 1 (identity 0.0)) ;; java.lang.ArithmeticException: Divide by zero

4个答案

0

评论来自:timmc

相关的代码似乎在 clojure.lang.Numbers/divide 中

if(yops.isZero((Number)y)) throw new ArithmeticException("Divide by zero");

让 Numbers/divide 的行为比双精度算术更严格似乎是一个错误;明确抛出 ArithmeticException 而不是让 JVM 处理,这似乎是不必要的额外工作。

0

评论来自:csm

我认为这个问题在于 clojure.lang.Numbers 中不同的除法变体有不同的语义。Numbers.divide(Object, Object) 执行 isZero 检查,但 Numbers.divide(long, double) 则不(它只使用 Java 的除法运算符,由于除数是一个值为 0.0 的 double,因此产生无穷大)。

类似于 (/ 1 0.0) 这样的语句会被编译成调用 Numbers.divide(long, double),从而产生无穷大。如果第二个参数是函数调用或变量,它看起来像一个对象,所以会被编译成使用 Numbers.divide(Object, Object),当第二个参数为零时,这个调用会抛出异常(实际上它编译成调用 Numbers.divide(long, Object),但这只是将第一个参数装箱并调用另一个变体)。

根据编译时推断的类型进行除法似乎是不正确的语义;然而,我不知道这是否影响除零以外的其他除法实例,所以这可能不是一个实际问题。

0

评论来自:timmc

bq.我不知道这是否影响除零以外的其他除法实例,所以这可能不是一个实际问题。

我认为只有有时失败的代码更糟糕,因为那时错误更有可能在生产环境中而不是开发环境中被发现。

0
参考资料:https://clojure.atlassian.net/browse/CLJ-1142(由 timmc 报告)
...