使用递归乘以方案

时间:2019-04-25 00:13:30

标签: recursion scheme racket

每当第二个数字(在这种情况下为y)为负数时,代码都不会给出答案,并最终崩溃。因此(RecursiveMultiply 9 3)有效,(RecursiveMultiply -9 3)有效,(RecursiveMultiply 9 -3)崩溃,(RecursiveMultiply -9 -3)崩溃。

这是我的代码

(define RecursiveMultiply 
  (lambda (x y) 
    (if (= y 1) 
        x
        (+ x (RecursiveMultiply x (- y 1))))))

3 个答案:

答案 0 :(得分:5)

如果y为负,您的过程将永远进行下去,您可以通过将if更改为cond来解决此问题,如果条件为y确实为负,则(if (= y 1) x (+ x (RecursiveMultiply x(- y 1))))的条件是使用不同的代码来容纳负数。

有问题的部分(define RecursiveMultiply (lambda(x y) (cond ((= y 1) x) ((= y 0) 0) ((< y 1) (* -1 (RecursiveMultiply x (- y)))) (else (+ x (RecursiveMultiply x (- y 1))))))) 基本上是说如果y为1,则返回x。如果y不为1,则在y递减后再次执行该过程。您的问题是,如果y为负或零,则该值已经小于1。从负数/零减去1只会推y越来越远。远离1,您将永远无法真正到达1。您的过程陷入无限循环,并导致解释器崩溃。

这是解决问题的方法:

(define (mult a b c)
  (define (double x)
    (* x 2))
  (define (halve x)
    (/ x 2))
  (cond ((= b 0) c)
        ((even? b)
          (mult (double a)(halve b) c))
        (else  
          (mult a (- b 1) (+ c a)))))
(define (two-number-mult x y)
    (mult x y 1))

我还要指出,您的过程很慢,它运行O(n),这意味着运行该过程所需的时间/空间随着输入的增长呈线性增长,这在处理大型时非常不好数字。我建议使它成为一个迭代函数,而不是使其运行O(log n),这是一个更快的函数。

以下是我编写的迭代乘法过程的示例,该过程运行O(n)最差情况和O(log n)最佳情况:

{{1}}

尝试用您的过程重新创建。

答案 1 :(得分:1)

您的递归函数的结束条件是“(= y 1)”。

但是当y为负数时,它永远不会满足这个条件,它变成了无限循环。

更改

(RecursiveMultiply x (- y 1)) 

(RecursiveMultiply x (- (abs y) 1))

欢迎来到美丽的球拍语言。

答案 2 :(得分:0)

注释#1:我对为什么使用(define f (lambda(arguments) ...))而不是(define (f arguments) ...)感到困惑。您还应该使用(sub1 y)而不是(- y 1)。此外,应将if替换为cond,这样会更清洁。

问题很简单,当y≠1时,您要从y中减去1,而当y为负数时,其值将无限期减小,从而形成一个无限循环,最终将使您的程序崩溃。

注释#2 :我已经按照“注释1”中的说明清理了您的某些代码

解决此问题的“专业”方法(在大多数学校中都是教授的)是创建 辅助功能 ,或者仅用于修改现有功能的功能功能。

;; Our auxiliary function
(define (RecursiveMultiply* x y)
(cond
  [(= y 1) x]
  [else (+ x (RecursiveMultiply x (- y 1)))]))

(define (RecursiveMultiply x y)
  (cond
    ;; Both "x" and "y" are negative, so change them both to positives
    [(and (< x 0) (< y 0)) (RecursiveMultiply* (abs x) (abs y))]
    ;; "y" is negative, so it Plugs in a legal "y" value and multiplies it by -1 to be mathematically correct
    ;; We should be using * instead of the first "RecursiveMultiply", but it is obvious that you want to do this without it
    [(< y 0) (RecursiveMultiply -1 (RecursiveMultiply* x (abs y)))]
    [else (RecursiveMultiply* x y)]))

示例:

(RecursiveMultiply 9 3) ; 27
(RecursiveMultiply -9 3)  ; -27
(RecursiveMultiply 9 -3)  ; -27
(RecursiveMultiply -9 -3) ; 27

它甚至可以与0一起使用!

(RecursiveMultiply -11 0) ; 0
(RecursiveMultiply 0 15) ; 0
(RecursiveMultiply 0 0) ; 0