简体   繁体   English

如何仅使用 C 中的按位运算符来检查值是否大于 7?

[英]How to check if values are greater than 7 by only using bitwise operators in C?

For this question, it asks to return 1 if the argument is greater than 7, and 0 otherwise.对于这个问题,它要求如果参数大于 7 则返回 1,否则返回 0。

For example, if x is 8, the function will return 1. If x is 7, the function will return 0.例如,如果 x 为 8,则 function 将返回 1。如果 x 为 7,则 function 将返回 0。

The only legal operators allowed are (, ~ & ^ | + << >>), which forbids the use of anything else such as -, for loops, while loops, if statements.唯一允许的合法运算符是 (, ~ & ^ | + << >>),它禁止使用任何其他内容,例如 -、for 循环、while 循环、if 语句。 etc.等等

We can assume the system uses 2's complement and a 32 bit representation of integers, performs right shifts arithmetically, and has unpredictable behavior when shifting an integer by more than the word size.我们可以假设系统使用 2 的补码和 32 位整数表示,执行算术右移,并且在将 integer 移位超过字长时具有不可预测的行为。

I know that subtracting without using the - operation can be done with ~, but I don't know how to think of this one logically to be honest.我知道不使用 - 操作的减法可以用 ~ 完成,但老实说,我不知道如何从逻辑上考虑这个。

In binary, the decimal number 7 is 111 .在二进制中,十进制数7111 Hence, a number which is greater than seven will always have a more significant bit set than the most significant bit in the binary representation of 7 (ie bit 3 when numbering from 0) set.因此,大于 7 的数字将始终具有比 7 的二进制表示中的最高有效位(即从 0 开始编号时的第 3 位)组更高的有效位组。 So, if you are dealing only with unsigned numbers then this test is sufficient:所以,如果你只处理无符号数,那么这个测试就足够了:

int bitwise_is_n_gt_7 (unsigned int value)
{
    return value & 0xFFFFFFF8; // assuming size 32-bits adjust as  necessary
} 

If you are dealing with signed numbers you have to also deal with the possibility that a number is negative, so you then test for:如果您正在处理带符号的数字,您还必须处理数字为负数的可能性,因此您需要测试:

int bitwise_is_n_gt_7 (int value)
{
    return (!!(value & 0x7FFFFFF8) & !(value & 0x80000000));
}

>7 is the same as ≥8. >7 等同于≥8。

You can check if a positive number is ≥ another positive number using integer division.您可以使用 integer 除法检查一个正数是否≥另一个正数。 It's larger if the result is non-zero.如果结果非零,它会更大。

Division isn't a "bit operation", but eight is a power of two, and there's a "bit operation" that's defined as a division by a power of 2: >>除法不是“位运算”,但 8 是 2 的幂,还有一种“位运算”被定义为除以 2 的幂: >>

So we could use:所以我们可以使用:

n >> 3

Right-shifting a positive integer by three removes the three least-significant bits while moving the others.将正 integer 右移三位会移除三个最低有效位,同时移动其他位。 But we don't care if the others are moved or not.但是我们不关心其他人是否被感动。

So we could also use:所以我们也可以使用:

n & ~7

If an unsigned number is 7 or less, then the only bits that will be set will be bits that represent 4 or 2 or 1 .如果无符号数为7或更小,则将设置的唯一位将是表示421的位。
The next higher bit represents 8 , which is greater than 7.下一个更高的位代表8 ,它大于 7。

So, if you "turn off" the lowest 3 bits (which represent 4 , 2 , and 1 ), with masking, and check if any bits still remain on, then the original number was 8 or greater.因此,如果您使用屏蔽“关闭”最低的 3 位(分别代表421 ),并检查是否还有任何位仍然存在,则原始数字为 8 或更大。

if (number & ~0b0111) // Turn OFF the lowest 3 bits, keep all the others.
{
    printf("Number is 8 or Greater\n");
}
else 
{
    printf("Number is 7 or less\n");
}

Using the 0b prefix is non-standard (but very common in many compilers), so you might choose to replace 0b0111 with 0x07 , or just plain-old 7 instead:使用0b前缀是非标准的(但在许多编译器中很常见),因此您可以选择将0b0111替换为0x07 ,或者只是普通的旧7

if (number & ~7)  { /* number is greater than 7 */ }

Example Code:示例代码:

#include <stdio.h>

int main(void) {
    for(int i=0; i<30; ++i)
    {
        printf("%d is %s 7\n", i, i&~7? "greater than" :"less than (or equal to)");
    }
    return 0;
}

Output Output

0 is less than (or equal to) 7
1 is less than (or equal to) 7
2 is less than (or equal to) 7
3 is less than (or equal to) 7
4 is less than (or equal to) 7
5 is less than (or equal to) 7
6 is less than (or equal to) 7
7 is less than (or equal to) 7
8 is greater than 7
9 is greater than 7
10 is greater than 7

Starting with this basic concept, and to handle negative numbers, you need to check if the "sign-bit" is set.从这个基本概念开始,为了处理负数,您需要检查是否设置了“符号位”。 If it is set, the number is automatically negative, and automatically less than 7.如果设置了,数字自动为负数,自动小于7。

Breaking it all down:打破这一切:

#include <stdio.h>
#include <stdbool.h>

int main(void) {
    for(int i=-10; i<+10; ++i)
    {
        bool is_negative_bit_off = !(i>>31);
        bool is_bit_8_or_higher_set = !!(i&~7);

        if (is_negative_bit_off && is_bit_8_or_higher_set)
        {
            printf("%d is greater than 7\n", i);
        }
    }
    return 0;
}

And then simplifying it:然后简化它:

int main(void) {
    for(int i=-10; i<+10; ++i)
    {
        bool num_greater_than_7 = !(i>>31) & !!(i&~7);

        if (num_greater_than_7)
        {
            printf("%d is greater than 7\n", i);
        }
    }
    return 0;
}

So the final expression / answer to your question is:所以你的问题的最终表达/答案是:

bool num_greater_than_7 = !(i>>31) & !!(i&~7);

(read as, "Is the Number Positive? And is the Number greater than 7?") (读作“这个数字是正数吗?这个数字是否大于 7?”)

Operators used are !使用的运算符是! , >> , & ~ . , >> , & ~

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

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