![](/img/trans.png)
[英]Algorithm for integer rounding of result after division of one integer by another whose values may be negative
[英]Integer Division Algorithm Analysis
对于赋值,我们需要编写除法算法,以便仅使用加法和递归来完成某个问题。 我发现,在不使用尾递归的情况下,天真的重复减法实现很容易导致堆栈溢出。 所以快速分析这个方法,如果我错了就纠正我,这表明如果你将A除以B,分别用n和m二进制数,它应该是以nm为指数。 我真的得到了
O( (n-m)*2^(n-m) )
因为你需要从n个二进制数字2 ^(nm)次中减去一个m二进制数字,以便将n位数字删除到n-1位数字,你需要这样做nm次来得到一个数字在重复减法除法中最多有m个数字,因此运行时应该如上所述。 再说一次,我很可能是错的,所以有人请你纠正我,如果我。 这是假设O(1)加法,因为我正在使用固定大小的整数。 我想用固定大小的整数可以说算法是O(1)。
回到我的主要问题。 我开发了一种不同的方法来执行整数除法,即使在递归使用它时,它也可以更好地工作,基于for的想法
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)
由于仅使用加法的限制,我只是在每次递归调用时将B添加到自身,但是这里是我的代码没有递归并且使用移位而不是添加。
int div( unsigned int m, unsigned int n )
{
// q is a temporary n, sum is the quotient
unsigned int q, sum = 0;
int i;
while( m > n )
{
i = 0;
q = n;
// double q until it's larger than m and record the exponent
while( q <= m )
{
q <<= 1;
++i;
}
i--;
q >>= 1; // q is one factor of 2 too large
sum += (1<<i); // add one bit of the quotient
m -= q; // new numerator
}
return sum;
}
我觉得sum |= (1<<i)
可能更合适,以强调我正在处理二进制表示,但它似乎没有给任何性能提升并且可能使它更难理解。 因此,如果M
和N
分别是m
和n
的位数,则分析表明内循环执行M - N
次,每次外循环完成m
失去一位,并且它也必须完成M - N
为了条件m <= n
, M - N
次,所以我得到它是O((M - N)^ 2)。
毕竟,我问我是否对算法的运行时间是否正确以及是否可以对其进行改进?
您的算法非常好,您对运行时间的分析是正确的,但您不需要每次都执行内部循环:
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;
}
这使它成为O(MN)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.