甚至? Scheme中的功能(Dr. Racket)

时间:2015-10-02 06:24:32

标签: recursion scheme

我正在尝试在Scheme中编写程序,以使用快速功率算法/递归来计算幂函数的结果。该算法应该是正确的,但在某些地方我的语法是关闭的。该程序编译,但当我输入一个基数和exp进行测试时,Dr。Racket冻结并耗尽内存。难以找到关于(偶数?)函数应如何出现在方案代码中的在线示例。我想这可能会抛弃我的语法。计划新,所以任何帮助将不胜感激。

(define (powFun base exp)
    (if ( = exp 0)                       //base case
     1                                     
       (even? exp                        //if exp is even
          (*
            (powFun base ( / exp 2))
            (powFun base ( / exp 2))
          )

       (*
          (powFun base (- exp 1) )      // else if exp is odd
           base 
       )
     )
  )

3 个答案:

答案 0 :(得分:4)

您似乎正在使用even?,就好像它是某种行为类似if的宏。但even?是一个带有一个参数的常规函数​​,因此您应该编写(even? exp)而不是(even? exp evaluate-if-even evaluate-if-not-even)。这意味着even?的返回值需要自己的if表达式:

(if base-case
   1
   (if (even? exp)
       evaluate-if-even
       evaluate-if-not-even))

...这意味着您应该使用cond

或者,您可以定义一个以您认为even?工作方式工作的宏。我们称之为if-even

(define-syntax if-even
    (syntax-rules ()
       ((_ n evaluate-if-even evaluate-if-not-even)
        (if (even? n) evaluate-if-even evaluate-if-not-even))))

然后使用even?替换原始程序中的if-even。更正使用even?然后切换为cond而不是if是更好的选择。

答案 1 :(得分:2)

even?if不相似 - 您使用它来测试一个数字是否均匀。
它没有"分支":

> (even? 2)
#t
> (even? 2 "even" "odd")
. . ..\..\Program Files (x86)\Racket\share\pkgs\drracket\drracket\private\rep.rkt:1088:24: even?: arity mismatch;
 the expected number of arguments does not match the given number
  expected: 1
  given: 3
  arguments...:
   2
   "even"
   "odd"

您可以在条件中将其用作测试:

> (if (even? 2) "even" "odd")
"even"

如果您想测试多个条件,使用cond代替if会很方便:

> (define x 3)
> (cond ((= x 1) "one")
         ((even? x) "even")
         (else "odd"))
"odd"

但这并不是DrRacket"冻结"的理由。

原因是除法不是整数除法,而是实际产生精确的小数结果:

> (/ 1 2)
1/2
> (/ (/ 1 2) 2)
1/4
> (/ (/ (/ 1 2) 2) 2)
1/8

所以你永远不会到达终止案例。

您应该使用quotient程序:

> (quotient 3 2)
1
> (quotient 2 2)
1
> (quotient 1 2)
0

利用sqr程序并更改" C风格" to" Scheme style",它可能如下所示:

(define (powFun base exp)
    (if (= exp 0) 
        1                                     
       (if (even? exp)
           (sqr (powFun base (quotient exp 2)))
           (* (powFun base (- exp 1)) base))))

或者

(define (powFun base exp)
    (cond ((= exp 0) 1)                                    
          ((even? exp) (sqr (powFun base (quotient exp 2))))
          (else (* (powFun base (- exp 1)) base))))

> (powFun 2 3)
8
> (powFun 2 0)
1
> (powFun 2 300)
2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397376

旁注:当您正在寻找问题时,交互窗口对于测试小部分代码非常有用。

答案 2 :(得分:1)

if只能使用不含关键字的最多2个子句thenelse。在这种情况下,您可以使用嵌套的ifcond。以下是cond

的示例
(cond ((= expr 0) 1)
      ((even? exp) #| do even ... |#)
      (else #| do odd |#))