Search code examples
lispracketsicp

SICP - Multiplication through addition


I am using the book SICP and attempting to solve this exercise:

1.2.4 Exponentiation

Exercise 1.18. Using the results of exercises 1.16 and 1.17, devise a procedure that generates an iterative process for multiplying two integers in terms of adding, doubling, and halving and uses a logarithmic number of steps

I am trying to solve this with the following code:

(define (double x) 
  (+ x x))

(define (halve x) 
  (floor (/ x 2)))

(define (* a b)
  (define (iter count accumulate)
    (cond ((= count 1) accumulate)
          ((even? a) (iter (halve count) (+ accumulate (double b))))
          (else empty)))
  (iter a 0))

As you might see, I am trying to deal with even numbers first. I am using the SICP wiki as my solutions-guide. They suggest some tests to see if the code works:

 (* 2 4) 
 (* 4 0) 

What I do not get is that my code passes on these two first tests, dealing only with even numbers.

However, when I try some big numbers which are multiples of two, the code fails. I checked the result using Python. For instance,

(IN PYTHON)

2**100  
>> 1267650600228229401496703205376  
2**98
>> 316912650057057350374175801344
a = 2**100
b = 2**98
a*b
>> 401734511064747568885490523085290650630550748445698208825344

When I use my function inside Dr. Racket with these values I get a different result:

(* 1267650600228229401496703205376 316912650057057350374175801344)

My result is: 63382530011411470074835160268800, which is wrong, as Python built-in functions suggest.

Why this is happening?


Solution

  • The recursive step seems wrong, and what's that empty doing there? also, what happens if b is negative? this solution should work:

    (define (mul a b)
      (define (iter a b acc)
        (cond ((zero? b) acc)
              ((even? b) (iter (double a) (halve b) acc))
              (else (iter a (- b 1) (+ a acc)))))
      (if (< b 0)
          (- (iter a (- b) 0))
          (iter a b 0)))
    

    For example:

    (mul 1267650600228229401496703205376 316912650057057350374175801344)
    => 401734511064747568885490523085290650630550748445698208825344