简体   繁体   English

如何使用按位运算符C表示否定

[英]How to represent negation using bitwise operators, C

Suppose you have 2 numbers: 假设您有2个数字:

int x = 1;
int y = 2;

Using bitwise operators, how can i represent xy ? 使用按位运算符,我怎么表示xy

When comparing the bits of two numbers A and B there are three posibilities. 比较两个数字AB的位时,存在三种可能性。 The following assumes unsigned numbers. 以下假定无符号数字。

  1. A == B : All of the bits are the same A == B :所有位都相同
  2. A > B : The most significant bit that differs between the two numbers is set in A and not in B A > B :两个数字之间的最高有效位是在A设置的,而不是在B
  3. A < B : The most significant bit that differs between the two numbers is set in B and not in A A < B :两个数字之间的最高有效位在B设置,而不在A

Code might look like the following 代码可能如下所示

int getDifType(uint32_t A, uint32_t B)
{
  uint32_t bitMask = 0x8000000;
  // From MSB to LSB
  for (bitMask = 0x80000000; 0 != bitMask; bitMask >>= 1)
  {
    if (A & bitMask != B & bitMask)
      return (A & bitMask) - (B & bitMask);
  }
  // No difference found
  return 0;
}

You need to read about two's complement arithmetic. 您需要阅读二进制补码算法。 Addition, subtraction, negation, sign testing, and everything else are all done by the hardware using bitwise operations, so you can definitely do it in your C program. 加,减,取反,符号测试以及其他所有操作都由硬件使用按位运算完成,因此您绝对可以在C程序中进行操作。 The wikipedia link above should teach you everything you need to know to solve your problem. 上面的Wikipedia链接应该教会您解决问题所需的一切。

Your first step will be to implement addition using only bitwise operators. 第一步将是仅使用按位运算符实现加法。 After that, everything should be easy. 之后,一切都应该变得容易。 Start small- what do you have to do to implement 00 + 00, 01 + 01, etc? 从小开始-要实现00 + 00、01 + 01等,您需要做什么? Go from there. 去那边

You need to start checking from the most significant end to find if a number is greater or not. 您需要从最重要的一端开始检查,以发现数字是否更大。 This logic will work only for non-negative integers. 此逻辑仅适用于非负整数。

int x,y;
//get x & y
unsigned int mask=1;           // make the mask 000..0001
mask=mask<<(8*sizeoF(int)-1);    // make the mask 1000..000

while(mask!=0)             
{
if(x & mask > y & mask)        
{printf("x greater");break;}
else if(y & mask > x & mask)
{printf("y greater");break;}
mask=mask>>1;                  // shift 1 in mask to the right
}

Compare the bits from left to right, looking for the leftmost bits that differ. 从左到右比较这些位,寻找最左边的位。 Assuming a machine that is two's complement, the topmost bit determines the sign and will have a flipped comparison sense versus the other bits. 假设机器为二进制补码,则最高位确定符号,并且与其他位相比,翻转的比较意义。 This should work on any two's complement machine: 这应该可以在任何两个的补码机上工作:

int compare(int x, int y) {
  unsigned int mask = ~0U - (~0U >> 1); // select left-most bit
  if (x & mask && ~y & mask)
    return -1; // x < 0 and y >= 0, therefore y > x
  else if (~x & mask && y & mask)
    return 1; // x >= 0 and y < 0, therefore x > y
  for (; mask; mask >>= 1) {
    if (x & mask && ~y & mask)
      return 1;
    else if (~x & mask && y & mask)
      return -1;
  }
  return 0;
}

[Note that this technically isn't portable. [请注意,从技术上讲,这是不可移植的。 C makes no guarantees that signed arithmetic will be two's complement. C不保证有符号算术将是二进制补码。 But you'll be hard pressed to find a C implementation on a modern machine that behaves differently.] 但是,您将很难在性能不同的现代机器上找到C实现。]

To see why this works, consider first comparing two unsigned numbers, 13d = 1101b and 11d = 1011b. 要了解为什么这样做,首先考虑比较两个无符号数13d = 1101b和11d = 1011b。 (I'm assuming a 4-bit wordsize for brevity.) The leftmost differing bit is the second from the left, which the former has set, while the other does not. (为简便起见,我假设使用4位的字长。)最左边的不同位是左边的第二位,前者已设置,而另一位则没有。 The former number is therefore the larger. 因此,前者更大。 It should be fairly clear that this principle holds for all unsigned numbers. 应当很清楚,该原则适用于所有无符号数字。

Now, consider two's complement numbers. 现在,考虑二进制补码。 You negate a number by complementing the bits and adding one. 通过对位进行补码并加一个来取反数字。 Thus, -1d = 1111b, -2d = 1110b, -3d = 1101b, -4d = 1100b, etc. You can see that two negative numbers can be compared as though they were unsigned. 因此,-1d = 1111b,-2d = 1110b,-3d = 1101b,-4d = 1100b,等等。您可以看到可以比较两个负数,就像它们是无符号的一样。 Likewise, two non-negative numbers can also be compared as though unsigned. 同样,两个非负数也可以比较,就像无符号一样。 Only when the signs differ do we have to consider them -- but if they differ, the comparison is trivial! 仅当符号不同时,我们才需要考虑它们-但是,如果它们不同,则比较是微不足道的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM