简体   繁体   English

用于在 c 中查找小于的按位运算符

[英]bitwise operators for finding less than in c

This is a homework assignment which requires me to come up with a function to determine if x < y , if it is I must return 1 , using only bitwise operators ( ! ~ & ^ | + << >> ) .这是一个家庭作业,需要我想出一个函数来确定x < y ,如果是,我必须返回1 ,只使用按位运算符( ! ~ & ^ | + << >> ) I am only allowed to use constants 0 - 0xFF , and assume a 32-bit integer.我只允许使用常量0 - 0xFF ,并假设一个 32 位整数。 No loops, casting, etc.没有循环,铸造等。

What I have figured out is that if you were to only examine say 4 bits you can do x - y to determine if x is less than y .我发现如果你只检查说 4 位,你可以做x - y来确定x是否小于y If x was 8 and y was 9 the result would be 1111 for -1 .如果x8并且y9则结果将为-1 1111

int lessThan(int x, int y){
    int sub = x + (~y+1); 

What I am confused about is how to go about now comparing that result with x to determine that it is indeed less than y .我感到困惑的是现在如何将该结果与x进行比较以确定它确实小于y

I have been examining this article here .我一直在这里检查这篇文章。

But I am a bit confused by that approach to the problem.但我对这种解决问题的方法感到有些困惑。 I have worked out the shifting to attain the bit smearing but am confused about how you go about using that result to compare the values as less than or greater than.我已经计算出移位以获得位拖尾,但我对如何使用该结果将值进行比较为小于或大于感到困惑。 I am just looking for a little guidance and clarity, not a solution, that is not my intent.我只是在寻找一些指导和清晰度,而不是解决方案,这不是我的意图。

The idea of implementing subtraction is good. 进行减法的想法很好。

int sub = x + (~y+1);

From here, you just need to check whether sub is negative, ie extract its sign bit. 从这里,您只需要检查sub是否为负,即提取其符号位。 This is where the technical difficulty appears. 这就是出现技术难题的地方。

Let's assume x and y are unsigned 32-bit integers. 假设xy是无符号的32位整数。 Then the result of subtraction can be represented by a signed 33-bit integer (check its minimum and maximum values to see that). 然后,可以用一个有符号的33位整数表示相减的结果(检查其最小值和最大值以查看该值)。 That is, using the expression x + (~y+1) directly doesn't help, because it will overflow. 也就是说,直接使用表达式x + (~y+1)没有帮助,因为它将溢出。

What if x and y were 31-bit unsigned numbers? 如果xy是31位无符号数字怎么办? Then, x + (~y+1) can be represented by a 32-bit signed number, and its sign bit tells us whether x is smaller than y : 然后, x + (~y+1)可以由一个32位带符号数表示,其符号位告诉我们x是否小于y

answer(x, y) := ((x + (~y+1)) >> 31) & 1

To convert x and y from 32 bits to 31 bits, separate their MSB (most significant bit) and all the other 31 bits into different variables: 要将xy从32位转换为31位,请将其MSB(最高有效位)和所有其他31位分开为不同的变量:

msb_x = (x >> 31) & 1;
msb_y = (y >> 31) & 1;
x_without_msb = x << 1 >> 1;
y_without_msb = y << 1 >> 1;

Then consider the 4 possible combinations of their MSB: 然后考虑其MSB的4种可能的组合:

if (msb_x == 0 && msb_y == 0)
    return answer(x_without_msb, y_without_msb);
else if (msb_x == 1 && msb_y == 0)
    return 0; // x is greater than y
else if (msb_x == 0 && msb_y == 1)
    return 1; // x is smaller than y
else
    return answer(x_without_msb, y_without_msb);

Converting all these if-statements to a single big ugly logical expression is "an exercise for the reader". 将所有这些if语句转换为一个大的丑陋逻辑表达式是“读者的一项练习”。

I think it can be achived doing following: 我认为可以做到以下几点:

  1. Xor both numbers, that will give you bits that differs 对两个数字进行“或”运算,这将为您提供不同的位数
  2. Get the most significant bit that differs, as this one will make a difference 获得最重要的不同点,因为这一点会有所作为
  3. Check if that most significant bit belongs to bigger value 检查最高有效位是否属于更大的值

Code: 码:

int less(int x, int y) {
    //Get only diffed bits
    int msb = x ^ y;
    //Get first msb bit
    msb |= (msb >>  1);
    msb |= (msb >>  2);
    msb |= (msb >>  4);
    msb |= (msb >>  8);
    msb |= (msb >> 16);
    msb = msb - (msb >> 1);
    //check if msb belongs to y;
    return !((y & msb) ^ msb);
}

这是我的尝试(编译结果,x> y然后为0,x <y然后为1,x == y然后为1):

((((x + ~y) >> 31) + 1))^1

Just wanted to add to this discussion, since I'm not sure if it's been mentioned yet.只是想添加到这个讨论中,因为我不确定是否有人提到过。 Some here have brought up that这里有些人提出了

( x + ((~y) + 1)) >> 32) & 0x1

will not work for overflow conditions.不适用于溢出条件。 For two's complement numbers, overflow conditions for adding integers x and y are:对于二进制补码,整数 x 和 y 相加的溢出条件为:

x > 0, y > 0, (x+y) < 0 x > 0, y > 0, (x+y) < 0

x < 0, y < 0, (x+y) > 0 x < 0, y < 0, (x+y) > 0

In this case, we're adding x and (-y) together, and must also check for overflow conditions before determining whether (xy)<0在这种情况下,我们将 x 和 (-y) 相加,并且在确定是否 (xy)<0 之前还必须检查溢出条件

long isLess(long x, long y) {
    long xs= (x>>63) & 0x1L; 
    long ys= (y>>63) & 0x1L;
    long s = x + (~y +1L);

    long ss= (s>>63) & 0x1L;

    /*
    //Code without SOP result for clarity
    if(xs & ~ys & ~ss) return 1;
    if(~xs & ys & ss)  return 0;

    return ss;
    */

    return (((xs | ~ys | ~ss) & (~xs | ys | ss)) & ss) |
           (((~xs & ys & ss) | (xs & ~ys & ~ss)) & ~ss);
}

In order to know if x < y , you can simply ask if x - y < 0 . 为了知道x < y ,您可以简单地询问x - y < 0

In other words, what is the sign of the result of x - y . 换句话说, x - y结果的符号是什么。

Since you stated you are to assume 32 bit integers, following will provide the correct result: 由于您已声明要假设32位整数,因此以下将提供正确的结果:

((x - y) >> 31) & 0x1

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

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