Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 整数除法算法分析_C_Algorithm_Runtime - Fatal编程技术网

C 整数除法算法分析

C 整数除法算法分析,c,algorithm,runtime,C,Algorithm,Runtime,对于作业,我们需要编写除法算法,以便只使用加法和递归来完成某个问题。我发现,如果不使用尾部递归,简单的重复减法实现很容易导致堆栈溢出。对这个方法做一个快速的分析,如果我错了,请纠正我,表明如果你用a除以B,分别用n和m个二进制数字,它应该是n-m的指数。我真的明白了 O( (n-m)*2^(n-m) ) 由于您需要从n个二进制数字中减去m个二进制数字2^(n-m)次,以便将n个数字减为n-1个数字,并且您需要执行n-m次,以获得重复减法除法中最多包含m个数字的数字,因此运行时应如前所述。再说

对于作业,我们需要编写除法算法,以便只使用加法和递归来完成某个问题。我发现,如果不使用尾部递归,简单的重复减法实现很容易导致堆栈溢出。对这个方法做一个快速的分析,如果我错了,请纠正我,表明如果你用a除以B,分别用n和m个二进制数字,它应该是n-m的指数。我真的明白了

O( (n-m)*2^(n-m) ) 
由于您需要从n个二进制数字中减去m个二进制数字2^(n-m)次,以便将n个数字减为n-1个数字,并且您需要执行n-m次,以获得重复减法除法中最多包含m个数字的数字,因此运行时应如前所述。再说一次,我很可能是错的,所以如果我是错的,请有人纠正我这是假设O(1)加法,因为我使用的是固定大小的整数。我想对于固定大小的整数,可以说算法是O(1)

回到我的主要问题。我开发了一种不同的方法来执行整数除法,这种方法工作得更好,即使在递归使用它时也是如此

p=2^(k_i)+。。。2^(K_0)

我们有

A/B = (A - B*P)/B + P
计算
A/B
的算法如下:

input:
    A, B

    i) Set Q = 0

   ii) Find the largest K such that B * 2^K <= A < B * 2(K + 1)

  iii) Q -> Q + 2^K

   iv) A -> A - B * 2^k

    v) Repeat steps ii) through iv) until A <= B

   vi) Return Q  (and A if you want the remainder)
输入:
A、 B
i) 设置Q=0
ii)求出最大K,使得B*2^K Q+2^K
iv)A->A-B*2^k
v) 重复步骤ii)至iv)直到A n)
{
i=0;
q=n;
//将q加倍,直到它大于m,然后记录指数

虽然(q您的算法非常好,您对运行时间的分析是正确的,但您不需要每次都进行内部循环:

unsigned div(unsigned num, unsigned den)
{
    //TODO check for divide by zero
    unsigned place=1;
    unsigned ret=0;
    while((num>>1) >= den) //overflow-safe check
    {
        place<<=1;
        den<<=1;
    }
    for( ;place>0; place>>=1,den>>=1)
    {
       if (num>=den)
       {
           num-=den;
           ret+=place;
       }
    }
    return ret;
}
unsigned div(unsigned num,unsigned den)
{
//TODO检查是否被零除
无符号位置=1;
无符号ret=0;
while((num>>1)>=den)//溢出安全检查
{
地点>=1)
{
如果(num>=den)
{
num-=den;
ret+=位置;
}
}
返回ret;
}

这使得它O(M-N)

q
同时(q
sum+=(1似乎您基本上是在描述长除法。“GCC是否能够将减法识别为除法,并用除法运算符替换它?”不,因为代码不是一个正确的除法。谢谢,这是一个非常好的改进;我甚至没有想到要保持移位分母和移位正确,而不是从头开始。
unsigned div(unsigned num, unsigned den)
{
    //TODO check for divide by zero
    unsigned place=1;
    unsigned ret=0;
    while((num>>1) >= den) //overflow-safe check
    {
        place<<=1;
        den<<=1;
    }
    for( ;place>0; place>>=1,den>>=1)
    {
       if (num>=den)
       {
           num-=den;
           ret+=place;
       }
    }
    return ret;
}