我正在尝试在C中实现乘法的加法和移位算法,但我的代码似乎没有正常工作。当我输入a = 35,b = 19时,代码返回0.当我输入a = -35,b = -19时,代码溢出。谁能发现我所缺少的东西?
void main(){
int a, b, c;
printf("Enter an integer: \n");
scanf("%d", &a);
printf("Enter an integer: \n");
scanf("%d", &b);
//multiply(a, b);
c = 0; //product
while(b != 0)
{
if(b & '\x01' == 1)
{
c = c + a;
}
a = a << 1;
b = b >> 1;
}
}
答案 0 :(得分:3)
当我输入a = 35,b = 19时,代码返回0
它适用于我,并提供预期的665
。
当我输入a = -35,b = -19时代码溢出
此算法不适用于负数。 << 1
和>> 1
的实现定义未定义负值。
在我的情况下(Visual Studio)b保持-1
并且循环永远不会结束。和
int i = -1;
printf("%d\n", i >> 1);
打印-1
。
答案 1 :(得分:0)
您需要了解整数的二进制代码,尤其是负整数。因为负数在二进制代码的开头有一个符号位,表示整数是负数或正数。机器通常在补码中记录一个整数,这使得负整数在二进制代码的开头可以有很多'1',这会使你的解决方案溢出。
以下是一个工作示例。
int a, b, c;
a = -35;
b = 19;
c = 0;
printf("b & 01 = %d, %d, a*b: %d\n", (b & '\x01'), '\x01', a*b);
bool negative = false;
if (a < 0) {
negative = !negative;
a = -a;
}
if (b < 0) {
negative = !negative;
b = -b;
}
while (b) {
if (b & 0x01) {
c += a;
}
a <<= 1;
b >>= 1;
printf("a: %d, b: %d, c: %d\n", a, b, c);
}
if (negative) {
c = -c;
}
printf("result: %d\n", c);
输出结果为:
a: 70, b: 9, c: 35
a: 140, b: 4, c: 105
a: 280, b: 2, c: 105
a: 560, b: 1, c: 105
a: 1120, b: 0, c: 665
result: -665
答案 2 :(得分:0)
当您将二进制转换为负值时,通常会将符号复制到最高位,使其与除以2的负数相同....所以如果使用-19
( 1111 1111 1111 1111 1111 1111 1110 1101
)然后向右移动一下,你得到(1111 1111 1111 1111 1111 1111 1111 0110
)-10
,然后你将完成-1(1111 1111 1111 1111 1111 1111 1111 1111
)永远不会== 0
。
您可以将两个数字转换为正数,然后在进行乘法运算之前将结果符号分开。我想你可以做到以下几点。如果b < 0,然后将符号更改为两个数字,否则执行乘法操作。
if (b < 0) {
b = -b; a = -a;
}
如果您使用unsigned int
类型,则会有所不同。在这种情况下,当您向右移动时,值的左侧会插入0。但在这种情况下,你会得到一个非常不同的结果。