我的代码在下面,它适用于大多数输入,但我注意到对于非常大的数字(2147483647除以特定示例的2),我得到分段错误并且程序停止工作。请注意,badd()和bsub()函数分别只是添加或减去整数。
unsigned int bdiv(unsigned int dividend, unsigned int divisor){
int quotient = 1;
if (divisor == dividend)
{
return 1;
}
else if (dividend < divisor)
{ return -1; }// this represents dividing by zero
quotient = badd(quotient, bdiv(bsub(dividend, divisor), divisor));
return quotient;
}
我的bmult()函数也遇到了一些麻烦。它适用于某些值,但程序失败的值为-8192次3.此功能也会列出。在此先感谢您的帮助。我真的很感激!
int bmult(int x,int y){
int total=0;
/*for (i = 31; i >= 0; i--)
{
total = total << 1;
if(y&1 ==1)
total = badd(total,x);
}
return total;*/
while (x != 0)
{
if ((x&1) != 0)
{
total = badd(total, y);
}
y <<= 1;
x >>= 1;
}
return total;
}
答案 0 :(得分:1)
bdiv的问题很可能是由递归深度引起的。在你给出的例子中,你将把大约1073741824帧放到堆栈上,基本上耗尽你分配的内存。
事实上,这个函数没有理由需要递归。我可以很容易地转换为迭代解决方案,缓解堆栈问题。
答案 1 :(得分:1)
在乘法中,此行会溢出并截断y
,因此badd()
输入错误:
y<<=1;
这一行:
x>>=1;
不能很好地为负x
工作。大多数编译器会在这里进行所谓的算术移位,这就像一个常规移位,0移位到最高位,但是有一个扭曲,最重要的位不会改变。所以,任何负值转移最终都会给你-1。向右移动的-1将保持为-1,从而导致乘法中出现无限循环。
您不应该使用该算法将无符号整数相乘以乘以有符号整数。如果它在核心中使用签名类型,则不太可能正常工作(如果有的话)。
如果要乘以有符号整数,可以先使用无符号类型对无符号整数进行乘法运算。然后你可以将它用于有符号乘法。这几乎适用于所有系统,因为它们使用带符号整数的2的补码表示。
示例(假设16位2的补码整数):
-1 * +1 - &gt; 0xFFFF * 1 = 0xFFFF - &gt;转换回签名 - &gt; -1
-1 * -1 - &gt; 0xFFFF * 0xFFFF = 0xFFFE0001 - &gt;截断为16位&amp;转换为签名 - &gt; 1
在分区中有以下两行
else if (dividend < divisor)
{ return -1; }// this represents dividing by zero
是完全错的。想想,1/2是多少?它是0,不是-1或(unsigned int)-1。
此外,UINT_MAX
/ 1多少钱?它是UINT_MAX
。因此,当您的除法函数返回UINT_MAX
或(unsigned int)-1
时,您将无法区分,因为这两个值是相同的。你真的应该使用不同的机制来通知调用者溢出。
哦,当然,这一行:
quotient = badd(quotient, bdiv(bsub(dividend, divisor), divisor));
当预期商数很大时,会导致堆栈溢出。不要递归地这样做。至少,请使用循环。