【问题标题】:Why does this implementation of Josef Stein's Binary GCD Algorithm only work for certain cases?为什么 Josef Stein 的二进制 GCD 算法的这种实现只适用于某些情况?
【发布时间】:2019-07-10 05:31:13
【问题描述】:

使用方案,我构建了二进制 GCD 算法(又名 Stein 算法)的迭代实现来计算数字 u 和 v 的最大公分母。该算法的步骤如下:

  1. gcd(0, v) = v,因为一切都除以零,而 v 是除 v 的最大数。同样,gcd(u, 0) = u。 gcd(0, 0) 通常没有定义,但设置 gcd(0, 0) = 0 很方便。
  2. 如果 u 和 v 都是偶数,则 gcd(u, v) = 2·gcd(u/2, v/2),因为 2 是公约数。
  3. 如果 u 是偶数而 v 是奇数,则 gcd(u, v) = gcd(u/2, v),因为 2 不是公约数。同样,如果 u 为奇数,v 为偶数,则 gcd(u, v) = gcd(u, v/2)。
  4. 如果 u 和 v 都是奇数,并且 u ≥ v,则 gcd(u, v) = gcd((u − v)/2, v)。如果两者都是奇数且 u

  5. 重复步骤 2–4 直到 u = v,或(再执行一步)直到 u = 0。在任何一种情况下,GCD 都是 2kv,其中 k 是在步骤 2 中找到的 2 的公因子数.

我做的算法是这样的:

(define (stein u v)
  (cond
    ((or (= u 0)(= u v))
      v)
    ((and (even? u) (even? v))
      (* 2 (stein (/ u 2)(/ v 2))))
    ((and (even? u) (odd? v))
      (stein (/ u 2) v))
    ((and (odd? u) (even? v))
      (stein u (/ v 2)))
    ((and (and (odd? u) (odd? v))(>= u v))
      (stein (/ 2 (- u v)) v))
    ((and (and (odd? u)(odd? v))(< u v))
      (stein (/ 2 (- v u)) u))))

我的问题是,每当我遇到一个数字是奇数而另一个数字是偶数的情况(输入是这种方式或过程最终以这种方式调用自己)时,输出要么是空白要么返回错误:Error: *: number required, but got #&lt;undef&gt; [stein, stein, stein, *]

有人可以解释为什么会发生这种情况以及如何解决它吗?

谢谢!

【问题讨论】:

  • 您应该在您的 cond 中放置一个“包罗万象”的案例,它会爆炸。您的案例旨在详尽无遗,但如果不是,您就没有抓住案例。 # 来自递归情况下的失败;您的较低级别的 stein 会通过 cond 并返回 #。更高级别的 stein 尝试将 # 乘以 2。
  • @Kaz 我该怎么做?
  • 例如(cond (whatever blah) ... (#t (this shouldn't be reached)))

标签: algorithm recursion runtime-error scheme lisp


【解决方案1】:

两行有错误:

(stein (/ 2 (- u v)) v))

和

(stein (/ 2 (- v u)) u))))

您应该将差值除以 2,而不是相反。那就是:

(stein (/ (- u v) 2) v))

和

(stein (/ (- v u) 2) u))))

最后,请注意,需要测试来检查第二个参数是否等于 0,否则在某些情况下函数会永远循环。

类似这样的:

(define (stein u v)
  (cond
    ((or (= u 0)(= u v))
      v)
    ((= v 0) u)
    ((and (even? u) (even? v))
      (* 2 (stein (/ u 2)(/ v 2))))
    ((and (even? u) (odd? v))
      (stein (/ u 2) v))
    ((and (odd? u) (even? v))
      (stein u (/ v 2)))
    ((and (and (odd? u) (odd? v))(>= u v))
      (stein (/ (- u v) 2) v))
    ((and (and (odd? u)(odd? v))(< u v))
      (stein (/ (- v u) 2) u))))

【讨论】:

  • 那是我没有发现的东西,但它并没有解决问题。
  • @Jodast,我在 DrRacket 中尝试过,它可以正确计算我所做的所有测试的 GCD。您正在使用哪种方案实现?什么是错误或未修复的问题?
  • 没关系,我在粘贴时删除了一个括号。它有效!
  • 我刚刚检查了 (4 0) 的算法,实际上它永远循环。需要为v = 0 添加显式文本以终止它。
  • @Jodast,我已更新答案以纠正该问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2012-06-08
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
相关资源
最近更新 更多