4

我刚刚开始学习 Lisp,并且正在解决一些 Project Euler 问题。我被困在你将偶数斐波那契数相加低于最大数的那个。我尝试过的事情如下。我读过这篇文章,但我仍然不确定为什么我的方法都不起作用!

CL-USER> (defun sum-even-fibs (max)
           (do ((curr 0 next)
                (next 1 (+ curr next))
                (sum  0 (if (evenp curr) (+ sum curr))))
               ((> max curr) sum)))
SUM-EVEN-FIBS
CL-USER> (sum-even-fibs 10)
0


CL-USER> (defun sum-even-fibs (max)
           (let ((sum 0))
             (do ((curr 0 next)
                  (next 1 (+ curr next)))
                 ((> max curr))
               (if (evenp curr) 
                   (setq sum (+ sum curr))))
             (format t "~d" sum)))
SUM-EVEN-FIBS
CL-USER> (sum-even-fibs 10)
0
NIL
4

3 回答 3

5

arbautjc 答案的稍微“更好”的版本:

(loop for a = 0 then b and b = 1 then (+ a b) 
      while (< a 4000000) 
      when (evenp a) sum a)
于 2013-05-02T14:53:01.463 回答
3

只要大于就终止do循环,这发生在第一次迭代中。 maxsum

但是,在将其切换>为 a之后<,您会得到一个算术错误,因为您最终会绑定sumnil(当您更新到(if (evenp curr) (+ sum curr))which is nilwhen(evenp curr)为 false 时。您还需要提供 else 端;它应该是sum.

更重要的是,do并行绑定其值,而不是按顺序绑定,这意味着对于第二次迭代,当您更新sum为时(if (evenp curr) (+ sum curr) sum),您使用的是第一次迭代中的currand sum。如果这不是您想要的,您应该考虑使用do*.

更新

根据评论中的要求,这是代码的完整工作版本。请注意,它与问题中的代码几乎相同;它只交换参数的顺序,以便在ent 斐波那契数大于imum 值>时终止,并将 else 情况添加到表达式中,以便当为 false 时,保留该值。currmaxif(evenp curr)sum

(defun sum-even-fibs (max)
  (do ((curr 0 next)
       (next 1 (+ curr next))
       (sum 0 (if (evenp curr) (+ sum curr) sum)))
      ((> curr max) sum)))
于 2013-05-02T02:28:19.150 回答
1

循环指令有很多不错的特性:

(loop with a = 0 and b = 1 
      while (< a 4000000) 
      when (evenp a)
      sum a
      do (psetf a b b (+ a b)))

请参阅Common Lisp HyperSpec 中的参考资料

于 2013-05-02T11:39:49.127 回答