Search code examples
schemelispracketsicp

How to do modulo in scheme


How would I do the following in sicp/scheme/dr. racket?

(define (even? n) (= (% n 2) 0))

Currently it seems like that's not a primitive symbol: %: unbound identifier in: %.

This may be the stupidest way in the world to do it, but without a % or bitwise-&1 I am doing (without logs or anything else):

(define (even? n)
  (if (< (abs n) 2)
       (= n 0)
       (even? (- n 2))))

Solution

  • I think it's a good practice to get comfortable writing your own procedures when it feels like they are "missing". You could implement your own mod as -

    (define (mod a b)
      (if (< a b)
          a
          (mod (- a b) b)))
    
    (mod 0 3) ; 0
    (mod 1 3) ; 1
    (mod 2 3) ; 2
    (mod 3 3) ; 0
    (mod 4 3) ; 1
    (mod 5 3) ; 2
    (mod 6 3) ; 0
    (mod 7 3) ; 1
    (mod 8 3) ; 2
    

    But maybe we make it more robust by supporting negative numbers and preventing caller from divi

    (define (mod a b)
      (if (= b 0)
          (error 'mod "division by zero")
          (rem (+ b (rem a b)) b)))
    
    (define (rem a b)
      (cond ((= b 0)
             (error 'rem "division by zero"))
            ((< b 0)
             (rem a (neg b)))
            ((< a 0)
             (neg (rem (neg a) b)))
            ((< a b)
             a)
            (else
             (rem (- a b) b))))