通过重复减法迭代模数?

时间:2013-10-02 04:25:33

标签: scheme

我正在尝试编写一个迭代过程来在方案中使用内置过程modulo,remainder或/在中进行模运算。但是在尝试编写代码时遇到了一些问题,到目前为止看起来像这样:

(define (mod a b)
    (define (mod-iter a b)
        (cond ((= b 0) 0)
              ((< b 0) (+ old_b new_b))))
    (mod-iter a (- a b)))

正如您所看到的,我遇到了需要将b的原始值添加到b的当前值的问题。我不知道该怎么做。另外,当我把第二个条件的答案留给原始数据时(只是为了确保enitre程序有效),我会得到一个“未指定的返回值”错误,我不知道为什么会发生这种情况,因为我的其余代码循环(或者似乎?)     提前感谢您对此的任何见解。

2 个答案:

答案 0 :(得分:0)

当您使用参数mod-iter定义(a b)函数时,您将隐藏mod中定义的参数。要避免阴影,请使用不同的标识符:

(define (mod a b)
  (define (mod-iter ax bx)
    (cond ((= bx 0) 0)
          ((< bx 0) (+ b bx))))
  (mod-iter a (- a b)))

注意,这看起来不像正确的算法(没有递归调用)。你如何处理(> bx 0)的常见情况?你需要这样的东西:

(define (mod a b)
  (define (mod-iter ax bx)
    (cond ((= bx 0) 0)
          ((< bx 0) (+ b bx))
          ((> bx 0) ...)))        ;; <- something here with mod-iter?
  (mod-iter a (- a b)))

答案 1 :(得分:0)

首先,如果您不想捕获变量名,请在内部函数中使用不同的变量名。其次,我认为与内置版本相比,这些论点是错误的。 (模5 6)是5,(模6 5)是1.无论如何,这里是对数时间的变化。基于生成b(2 4 8 16 32 ...)的幂列表,b是2,一直到a的值之下。然后通过机会减去这些反转值。那样的问题(mod(expt 267 34)85)很快就会回答问题。 (几百个原始函数调用与几百万)

(define (mod a-in b-in)
 (letrec ((a (abs a-in))
           (sign (if (< 0 b-in) - +))
           (b (abs b-in))
       (powers-list-calc 
        (lambda (next-exponent) 
          (cond ((> b a) '())
            ((=  next-exponent 0) 
            (error "Number 0 passed as the second argument to mod 
                is not in the correct range"))
                   (else (cons next-exponent (powers-list (* b next-exponent))))))))
    (let ((powers-list (reverse (powers-list-calc b))))
      (sign
    (let loop ((a a) (powers-L powers-list))
          (cond ((null? powers-L) a)
                ((> a (car powers-L))
            (loop (- a (car powers-L)) powers-L))
                (else (loop a (cdr powers-L)))))))))