简体   繁体   中英

Even? function in Scheme (Dr. Racket)

I'm trying to write a program in Scheme to compute the result of the power function using the fast power algorithm/recursion. The algorithm should be correct, but somewhere my syntax is off. The program compiles, but when I input a base and exp to test, Dr. Racket freezes up and runs out of memory. Having a difficult time locating online examples for how the (even?) function should appear in scheme code. I think this might be throwing my syntax off. New to scheme so any help would be much appreciated.

(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 
       )
     )
  )

)

You seem to be using even? as if it was some kind of macro that behaves like if . But even? is a regular function that takes one argument, so you should have written (even? exp) and not (even? exp evaluate-if-even evaluate-if-not-even) . That means the return value of even? needs its own if expression:

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

...which means you should be using cond instead.

Or, you could define a macro that works the way you thought even? worked. Let's call it 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))))

Then replace even? in your original program with if-even . Correcting your use of even? and then switching to cond instead of if is the better option, though.

even? is not similar to if - you use it to test whether one number is even.
It does not have "branches":

> (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"

You can use it as a test in a conditional:

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

If you want to test several conditions, it's convenient to use cond instead of if :

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

But that's not the reason for DrRacket "freezing".

The reason for that is that the division is not an integer division but actually produces an exact fractional result:

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

so you will never reach the terminating case.

You should use the quotient procedure:

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

Making use of the sqr procedure and changing your brackets from "C style" to "Scheme style", it might look like this:

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

Or

(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

Side note: the interaction window is extremely useful for testing small parts of code when you're looking for a problem.

if can only take max 2 clauses, then and else without keyword. In this situation, you can either use nested if or cond . Following is an example of cond :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM