Scheme 用递归法求级数的条件和

Scheme 用递归法求级数的条件和,scheme,lisp,racket,Scheme,Lisp,Racket,我是个新手。我需要将所有小于1000(或任何第n个值)的自然数相加,这些数可以被3或5整除。我有一个代码可以做到这一点,但使用迭代。但我必须通过递归做同样的事情。代码如下: (define (sum-divisibles limit) (for/sum ([i (in-range 1 limit)] #:when (or (divides? i 3) (divides? i 5))) i)) (define (d

我是个新手。我需要将所有小于1000(或任何第n个值)的自然数相加,这些数可以被3或5整除。我有一个代码可以做到这一点,但使用迭代。但我必须通过递归做同样的事情。代码如下:

(define (sum-divisibles limit)
  (for/sum ([i (in-range 1 limit)]
            #:when (or (divides? i 3)
                       (divides? i 5)))
    i))

(define (divides? m n)
  (= 0 (remainder m n)))  

我需要做同样的事情,但是使用递归,而不是循环或迭代。

n
为正数,
m
为前导,
m=n-1

现在,假设您知道
(总和可除数m)
等于某个值
s
。您将如何计算
(可除和n)

尝试编写一个函数,该函数接受一个值
n
和一个值
s
,并计算
n
的和

 (define (recur n s) ...)

然后,您将能够根据
限制定义
总和可除数
,并为
限制-1
递归应用
总和可除数
。当
limit
为零时,您还需要注意递归的基本情况。

这很简单,只要您将循环中的每个迭代可视化为函数调用。想想看:原来的
for
循环从
1
一直到并包括
limit-1
。这与从
limit-1
开始,在每次函数调用时将限制降低
1
,并在到达
0
时停止相同

编写递归过程时要记住两件重要的事情:

  • 我们必须确保我们在某个点停止——这被称为基本情况;对于本例,当我们到达
    0
    (因为原始循环包括
    1
    )时就会发生这种情况
  • 我们必须结合调用递归时得到的部分结果:如果当前数字恰好可以被
    3
    5
    整除,那么我们将其添加到其余的递归调用中,否则我们将忽略它,但仍然继续推进递归,直到达到基本情况
  • 这就是我的意思:

    (define (sum-divisibles limit)
      (cond ((= limit 0) 0)                             ; base case, stop recursion
            ((or (divides? limit 3) (divides? limit 5)) ; does the condition hold?
             (+ limit                                   ; then we add current value
                (sum-divisibles (- limit 1))))          ; and advance the recursion
            (else                                       ; otherwise skip it
             (sum-divisibles (- limit 1)))))            ; and advance the recursion
    
    小心初始的
    限制
    值,请记住,在原始代码中,
    限制
    不会添加到总和中(迭代在到达之前停止),因此调用递归版本的等效方法如下:

    (sum-divisibles (- n 1))
    
    例如,要使用代码获得与
    (sum divisibles 50)
    相同的值,我们必须在递归版本中这样调用它:

    (sum-divisibles 49)
    => 543
    

    或者,您可以编写一个助手过程,在调用实际的递归过程之前,将输入限制减少一,但这留给读者作为练习。

    可以使用“命名let”进行递归:

    (define limit 1000)
    
    (let loop ((n 1)                 ; starting values
               (sum 0))
      (cond
        [(> n limit) sum]            ; print out sum if limit reached;
    
        [(or (= 0 (modulo n 3))      ; if n is divisible by 3 or 5
             (= 0 (modulo n 5)))
         (loop (add1 n) (+ sum n))]  ; add this number to sum and loop again with next number
    
        [else                        ; if not divisible
         (loop (add1 n) sum)]        ; loop with next number without adding to sum
        ))
    

    @数据政策公司。这个或其他答案解决了你的问题吗?如果是这样,请不要忘记接受和/或投票选出最佳答案,以鼓励海报;)嗨,奥斯卡。谢谢你的解释。现在我很清楚了,我明白了一切。现在,我正在尝试为您所说的(N-1)案例创建一个帮助函数。您好,非常感谢。现在我很清楚了。