Algorithm 除法算法

Algorithm 除法算法,algorithm,division,Algorithm,Division,我刚开始学习设计分析和算法课程,我们从简单的算法开始 有一种除法算法我搞不懂 函数除法(x,) 输入:2个整数x和y,其中y>=1 输出:商和x除以y的余数 if x=0: return (q,r)=(0,0) (q,r)=divide(floor (x/2), y) q=2q, r=2r if x is odd: r=r+1 if r>=y: r=r-y, q=q+1 return(q,r) * floor is lower bound 我们

我刚开始学习设计分析和算法课程,我们从简单的算法开始

有一种除法算法我搞不懂

函数除法(x,) 输入:2个整数x和y,其中y>=1 输出:商和x除以y的余数

  if x=0: return (q,r)=(0,0)
   (q,r)=divide(floor (x/2), y)
   q=2q, r=2r

   if x is odd: r=r+1
   if r>=y: r=r-y, q=q+1
   return(q,r)

   * floor is lower bound
我们应该用这个算法来计算110011%101(二进制值)…我尝试了一些东西,得到了一个奇怪的答案…转换成十进制值,结果是错误的

所以我先用简单的十进制值代替二进制值

x=25, y=5

This is what I'm doing

1st: q=x,r= 12,5
2nd: q=x,r= 6,5
3rd: q=x,r= 3,5
4th: q=x,r= 1,5
5th: q=x,r= 0,5
这东西怎么用?每次我运行它时,last x的最后一个值将为0(条件),它将停止并返回q=0,r=0

谁能告诉我哪里出了问题


谢谢

函数有一个递归结构,这可能是它有点棘手的原因。我假设函数声明中有一个输入错误,其中divide(x,)应该是divide(x,y)。假设期望的结果是x/y和余数,让我们继续。函数定义中的第一行声明,如果分子为0,则返回0,余数为0。这是有道理的:而b!=0和a=0,所有整数的a/b=0。然后,我们将结果设置为一个递归调用,使用一半的原始分子和当前分母。在某一点上,“原分子的一半”变成0,并达到基本情况。在每个递归调用的末尾都会有一些计算,这似乎是尾部递归。因为我们在每次加深时除以2,再乘以2得到原始结果,如果余数是奇数,则在余数上加1。单独在文本中很难形象化,所以请用给定的问题在纸上逐步完成

从数学上讲,除法算法(称为除法)规定,当输入25,5时,余数必须小于或等于5

算法给出了0,5。这可能意味着当商为0时,不考虑余数,或者需要对余数的大小进行检查。
function divide(x,) Input: 2 integers x and y where y>=1 Output: quotient and remainder of x divided by y

  if x=0: return (q,r)=(0,0)
   (q,r)=divide(floor (x/2), y)
   q=2q, r=2r

   if x is odd: r=r+1
   if r>=y: r=r-y, q=q+1
   return(q,r)

   * floor is lower bound

该函数有一个递归结构,这可能是它有点棘手的原因。我假设函数声明中有一个输入错误,其中divide(x,)应该是divide(x,y)。假设期望的结果是x/y和余数,让我们继续。函数定义中的第一行声明,如果分子为0,则返回0,余数为0。这是有道理的:而b!=0和a=0,所有整数的a/b=0。然后,我们将结果设置为一个递归调用,使用一半的原始分子和当前分母。在某一点上,“原分子的一半”变成0,并达到基本情况。在每个递归调用的末尾都会有一些计算,这似乎是尾部递归。因为我们在每次加深时除以2,再乘以2得到原始结果,如果余数是奇数,则在余数上加1。单独在文本中很难形象化,所以请用给定的问题在纸上逐步完成

从数学上讲,除法算法(称为除法)规定,当输入25,5时,余数必须小于或等于5

算法给出了0,5。这可能意味着当商为0时,不考虑余数,或者需要对余数的大小进行检查。
function divide(x,) Input: 2 integers x and y where y>=1 Output: quotient and remainder of x divided by y

  if x=0: return (q,r)=(0,0)
   (q,r)=divide(floor (x/2), y)
   q=2q, r=2r

   if x is odd: r=r+1
   if r>=y: r=r-y, q=q+1
   return(q,r)

   * floor is lower bound

我用Ruby实现了您的算法(arg列表中有明显的更正):


它正在工作,所以当您试图手动跟踪递归时,一定不能正确地跟踪它。我发现为每个递归调用在一张新的纸上写出逻辑并将旧的纸放在以前调用的堆栈上是很有帮助的。当我在当前工作表上找到一个return语句时,把它卷起来,扔掉,然后在堆栈顶部的一张纸上写下返回值来代替递归调用。继续执行此工作表上的逻辑,直到到达另一个递归调用或返回。继续重复此操作,直到堆栈上的纸张用完为止-最后一张纸的返回是最终答案。

我用Ruby实现了您的算法(在arg列表中有明显的更正):


它正在工作,所以当您试图手动跟踪递归时,一定不能正确地跟踪它。我发现为每个递归调用在一张新的纸上写出逻辑并将旧的纸放在以前调用的堆栈上是很有帮助的。当我在当前工作表上找到一个return语句时,把它卷起来,扔掉,然后在堆栈顶部的一张纸上写下返回值来代替递归调用。继续执行此工作表上的逻辑,直到到达另一个递归调用或返回。不断重复这个步骤,直到堆栈上的纸张用完为止-最后一张纸的返回就是最终答案。

如果我没记错的话,这是在简单ALU中进行整数除法的最基本方法之一。这很好,因为您可以并行运行所有递归除法,因为每个除法都是基于只查看二进制文件的一个较少的位

要理解它的作用,只需按照Chris Zhang的建议,在纸上浏览一下即可。下面是
除法(25,5)
的样子:

(x,y)=(25,5)
    divide(12, 5)
        divide(6,5)
            divide(3,5)
                divide(1,5)
                    divide(0,5) // x = 0!
                    return(0,0)
                (q,r)=(2*0,2*0)
                x is odd, so (q,r)=(0,1)
                r < y
                return(0,1)
            (q,r)=(2*0,2*1)
            x is odd, so (q,r)=(0,3)
            r < y
            return(0,3)
        (q,r)=(2*0,2*3)
        x is even
        r >= y, so (q,r)=(1,1)
        return(1,1)
    (q,r)=(2*1,2*1)
    x is even
    r < y
    return(2,2)
(q,r)=(2*2,2*2)
x is odd, so (q,r)=(4,5)
r >= y, so (q,r)=(5,0)
return(5,0)
(x,y)=(25,5)
除法(12,5)
除法(6,5)
除法(3,5)
除以(1,5)
除以(0,5)//x=0!
返回(0,0)
(q,r)=(2*0,2*0)
x是奇数,所以(q,r)=(0,1)
r=y,so(q,r)=(1,1)
返回(1,1)
(q,r)=(2*1,2*1)
x是偶数
r=y,so(q,r)=(5,0)
回报率(5,0)
正如你所看到的,它起作用了——它给你一个5的q和一个0的r。你注意到的部分是,你最终会有一个0的术语,Chris恰当地称之为“基数”