Clojure在函数中减少溢出,但在直接传递到REPL时不会

时间:2016-12-16 11:29:39

标签: clojure reduce

我在调试溢出时遇到很大麻烦,只有当我在函数中使用语句时才会发生溢出。

这是我的功能:

(defn sum-records
    [senset votemap]
    (let [voteset (select-keys votemap senset)]
        (reduce (fn [v1 v2] (mapv + v1 v1)) (vals voteset))))

问题似乎来自reduce。但是,当我在数据的repl中自己运行该行时,它的工作完全正常。我已经检查过以确保我在repl上测试的数据确实与函数中的voteset相同。我甚至在函数中插入了println语句来验证这一点。

我真的被困在这里,非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

您可能有整数溢出:

 (reduce (fn [v1 v2] (mapv + v1 v1)) (repeat 1000 (range 10)))
 => ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1501)

您必须确保输入数据为其他内容,或者在+函数中强制转换为bigint,或者使用支持任意精度的@ClojureMostly指出的+'

所有这些方法都有效:

  (reduce (fn [v1 v2] (mapv +' v1 v1)) (repeat 1000 (range 0 10)))
   => [0N 535754303593133660474212524...

  (reduce (fn [v1 v2] (mapv + v1 v1)) (repeat 1000 (range 0N 10N)))
   => [0N 535754303593133660474212524...

  (reduce (fn [v1 v2] (mapv + v1 v1)) (repeat 1000 (map bigint (range 10))))
   => [0N 5357543035931336604742125245300009052...

  (reduce (fn [v1 v2] (mapv #(+ (bigint %1) (bigint %2)) v1 v1)) (repeat 1000 (range 10)))
   => [0N 53575430359313366...