【问题标题】:Integer overflow using lazy sequences in ClojureClojure 中使用惰性序列的整数溢出
【发布时间】:2012-06-27 03:46:42
【问题描述】:

我刚刚学习在 Clojure 中使用惰性序列,我不确定我在以下代码中做错了什么:

(defn sum [seqn]
  (reduce + seqn))

(defn fib
  ([] (concat [0 1] (fib 0 1)))
  ([a b] (lazy-seq (cons (+ a b) (fib b (+ a b))))))

(defn up-to [n seqn]
  (filter (fn [x] (< x n)) seqn))

(sum (up-to 100 (fib))) => ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)

求和的数字不应该大于100,那么是什么导致整数溢出?

【问题讨论】:

  • 我遇到了这个问题,试图解决同样的问题:Project Euler,问题编号 2!

标签: clojure lazy-evaluation integer-overflow


【解决方案1】:

过滤一个无限序列会产生一个无限序列,并且在此之上减少会导致过滤器继续寻找另一个匹配项,即使在谓词停止返回 true 之后也是如此。

filter 替换为take-while(fib) 生成的无限序列将导致filter 永远运行,但在此之前它会由于您正在经历的ArithmeticException 而中断。 take-while 将在 (fn [x] (&lt; x n)) 谓词评估为 false 后停止对列表的进一步评估。

(defn up-to [n seqn]
  (take-while (fn [x] (< x n)) seqn))

(sum (up-to 100 (fib))) ;; => 232

【讨论】:

  • 过滤器如何评估整个列表?我认为它应该产生一个惰性序列?
  • 没关系,我明白了……这不是过滤器本身。过滤一个无限序列会产生一个无限序列,并且在此之上减少会导致过滤器继续寻找另一个匹配项,即使在谓词停止返回 true 之后也是如此。
  • 知道了,Alex 的推理似乎比答案更准确。请更新答案,以便我将其标记为正确。
  • 彻坦,完成。现在剪了吗? @Alex,感谢您的 cmets。
  • 一个很好的方法,让您了解 Take-while 和 filter 之间的区别。
【解决方案2】:

从 clojure 1.3.0 开始的数字不会自动升级为 bigInt/bigDecimal。

要解决此问题,请改用+'

你的第 100 个 fibinachi 数字对于整数来说太大了

user> (nth (fib) 100)
354224848179261915075N

【讨论】:

  • 我认为他不是在对前 100 个斐波那契数进行求和,而是对小于 100 的斐波那契数求和。
  • 是的,这是针对与 Jan 的答案中解决的问题不同的问题的单独答案。
猜你喜欢
  • 2010-12-08
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多