Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 等价于大于运算符的位运算_C_Binary_Bit Manipulation - Fatal编程技术网

C 等价于大于运算符的位运算

C 等价于大于运算符的位运算,c,binary,bit-manipulation,C,Binary,Bit Manipulation,我正在研究一个函数,它基本上可以看出两个int中哪个更大。传递的参数是232位整数。诀窍是只允许使用!~ |&>^(无强制转换,除带符号的int、*、/、-等以外的其他数据类型) 到目前为止,我的想法是将这两个二进制文件放在一起,以查看它们不共享的1值的所有位置。然后我想做的是取那个值并将最左边的1隔离。然后看看哪一个有这个价值。然后该值将更大。 (假设我们使用8位整数而不是32位整数)。 如果传递的两个值分别为01011011和01101001 我对它们使用了^来获得00100010。 然后我

我正在研究一个函数,它基本上可以看出两个int中哪个更大。传递的参数是
2
32位整数。诀窍是只允许使用
!~ |&>^(无强制转换,除带符号的int、*、/、-等以外的其他数据类型)

到目前为止,我的想法是将这两个二进制文件放在一起,以查看它们不共享的
1
值的所有位置。然后我想做的是取那个值并将最左边的
1
隔离。然后看看哪一个有这个价值。然后该值将更大。 (假设我们使用8位整数而不是32位整数)。 如果传递的两个值分别为
01011011
01101001
我对它们使用了
^
来获得
00100010
。 然后我想让它成为
00100000
,换句话说
01xxxxxx->01000000
然后
&
使用第一个数字
结果并返回它。
如果是
1
,则第一个
#
较大

关于如何
01xxxxxx->01000000
或其他有帮助的方法,您有什么想法吗

忘了注意:没有ifs、whiles、fors等…

编辑: 好的,代码有一些问题,但我修改了它,并进行了以下工作

此辅助功能比较第n个有效数字:

int compare ( int a, int b, int n )
{
    int digit = (0x1 << n-1);
    if ( (a & digit) && (b & digit) )
       return 0; //the digit is the same

    if ( (a & digit) && !(b & digit) )
       return 1; //a is greater than b

    if ( !(a & digit) && (b & digit) )
       return -1; //b is greater than a
}

编辑:约束使底部的简单方法无效。我正在添加二进制搜索函数和最终比较,以检测更大的值:

unsigned long greater(unsigned long a, unsigned long b) {
    unsigned long x = a;
    unsigned long y = b;
    unsigned long t = a ^ b;
    if (t & 0xFFFF0000) {
        x >>= 16;
        y >>= 16;
        t >>= 16;
    }
    if (t & 0xFF00) {
        x >>= 8;
        y >>= 8;
        t >>= 8;
    }
    if (t & 0xf0) {
        x >>= 4;
        y >>= 4;
        t >>= 4;
    }
    if ( t & 0xc) {
        x >>= 2;
        y >>= 2;
        t >>= 2;
    }
    if ( t & 0x2) {
        x >>= 1;
        y >>= 1;
        t >>= 1;
    }
    return (x & 1) ? a : b;
}
我们的想法是从我们感兴趣的单词的最重要的一半开始,看看其中是否有任何设定位。如果有,那么我们不需要最低有效的一半,所以我们将不需要的位移开。如果不是,我们什么也不做(反正一半是零,所以不会碍事)。由于我们无法跟踪移位量(这需要加法),因此我们也会移位原始值,以便我们可以进行最后的
以确定较大的数字。我们用上一个掩码的一半大小重复这个过程,直到我们将感兴趣的位折叠到位位置0为止

我不是故意在这里加上同样的例子的


旧答案:

对于家庭作业来说,最简单的方法可能是最好的。一旦获得了不匹配的位值,就从另一个掩码0x8000000(或适合字大小的任何合适的最大位位置)开始,并保持右移,直到达到设置在不匹配值中的位为止。如果右移以0结束,则不匹配值为0


我假设您已经知道确定较大数字所需的最后一步。

这里有一个无循环版本,它比较O(lg b)运算中的无符号整数,其中b是机器的字长。请注意,OP只说明了
signed int
,没有其他数据类型,因此此答案的顶部似乎不符合OP的规范。(扰流板版本与底部相同。)

请注意,我们要捕获的行为是,对于
a
而言,最重要的位不匹配是
1
,对于
b
而言,最重要的位不匹配是
0
。另一种思考方式是
a
中的任何位大于
b
中的相应位意味着
a
大于
b
,只要
a
中没有早于
b
中相应位的位

为此,我们计算
a
中大于
b
中相应位的所有位,同样地计算
a
中小于
b
中相应位的所有位。我们现在想屏蔽掉所有低于“小于”位的“大于”位,所以我们将所有的“小于”位都涂抹到右边,制作一个屏蔽:最重要的位设置一直到最不重要的位现在是
1

现在我们所要做的就是通过使用简单的位屏蔽逻辑删除“大于”位集

如果
ab
,则结果值为0。在后一种情况下,如果我们希望它是
1
,我们可以执行类似的涂抹技巧,只需查看最低有效位

#include <stdio.h>

// Works for unsigned ints.
// Scroll down to the "actual algorithm" to see the interesting code.

// Utility function for displaying binary representation of an unsigned integer
void printBin(unsigned int x) {
    for (int i = 31; i >= 0; i--) printf("%i", (x >> i) & 1);
    printf("\n");
}
// Utility function to print out a separator
void printSep() {
    for (int i = 31; i>= 0; i--) printf("-");
    printf("\n");
}

int main()
{
    while (1)
    {
        unsigned int a, b;

        printf("Enter two unsigned integers separated by spaces: ");
        scanf("%u %u", &a, &b);
        getchar();

        printBin(a);
        printBin(b);
        printSep();

            /************ The actual algorithm starts here ************/

        // These are all the bits in a that are less than their corresponding bits in b.
        unsigned int ltb = ~a & b;

        // These are all the bits in a that are greater than their corresponding bits in b.
        unsigned int gtb = a & ~b;

        ltb |= ltb >> 1;
        ltb |= ltb >> 2;
        ltb |= ltb >> 4;
        ltb |= ltb >> 8;
        ltb |= ltb >> 16;

        // Nonzero if a > b
        // Zero if a <= b
        unsigned int isGt = gtb & ~ltb;

        // If you want to make this exactly '1' when nonzero do this part:
        isGt |= isGt >> 1;
        isGt |= isGt >> 2;
        isGt |= isGt >> 4;
        isGt |= isGt >> 8;
        isGt |= isGt >> 16;
        isGt &= 1;

            /************ The actual algorithm ends here ************/

        // Print out the results.
        printBin(ltb); // Debug info
        printBin(gtb); // Debug info
        printSep();
        printBin(isGt); // The actual result
    }
}
我会留下来解释为什么它由您决定。

一个无符号变量,它可以使用逻辑(&&,| | |)和比较(!=,=)

对于签名用户,可以扩展到以下内容:

int isgt(int a, int b)
{
    return
    (a != b) &&
    (
        (!(0x80000000 & a) && 0x80000000 & b) ||  /* if a >= 0 && b < 0  */
        (!(0x80000000 & a) && b == 0) ||
        /* Two more lines, can add them if you like, but as it is homework
         * I'll leave it up to you to decide. 
         * Hint: check on "both negative" and "both not negative". */
    )
    ;
}
使用此项测试:

void test_isgt(int a, int b)
{
    fprintf(stdout,
        "%11d > %11d = %d : %d %s\n",
        a, b,
        isgt(a, b), (a > b),
        isgt(a, b) != (a>b) ? "BAD!" : "OK!");
}
结果:

         33 >           0 = 1 : 1 OK!
        -33 >           0 = 0 : 0 OK!
          0 >          33 = 0 : 0 OK!
          0 >         -33 = 1 : 1 OK!
          0 >           0 = 0 : 0 OK!
         33 >          33 = 0 : 0 OK!
        -33 >         -33 = 0 : 0 OK!
         -5 >         -33 = 1 : 1 OK!
        -33 >          -5 = 0 : 0 OK!
-2147483647 >  2147483647 = 0 : 0 OK!
 2147483647 > -2147483647 = 1 : 1 OK!
 2147483647 >  2147483647 = 0 : 0 OK!
 2147483647 >           0 = 1 : 1 OK!
          0 >  2147483647 = 0 : 0 OK!

虽然我不想做别人的家庭作业,但我还是忍不住要做这件事:)我相信其他人可以想出一个更紧凑的…但这是我的…效果很好,包括负数

编辑:不过有几个bug。我将把它留给OP去发现它并修复它

    #include<unistd.h>
    #include<stdio.h>
    int a, b, i, ma, mb, a_neg, b_neg, stop;

    int flipnum(int *num, int *is_neg) {
        *num = ~(*num) + 1;
        *is_neg = 1;

        return 0;
    }

    int print_num1() {
        return ((a_neg && printf("bigger number %d\n", mb)) ||
             printf("bigger number %d\n", ma));
    }

    int print_num2() {
        return ((b_neg && printf("bigger number %d\n", ma)) ||
             printf("bigger number %d\n", mb));
    }

    int check_num1(int j) {
        return ((a & j) && print_num1());
    }

    int check_num2(int j) {
        return ((b & j) && print_num2());
    }

    int recursive_check (int j) {
        ((a & j) ^ (b & j)) && (check_num1(j) || check_num2(j))  && (stop = 1, j = 0);

        return(!stop && (j = j >> 1) && recursive_check(j));
    }

    int main() {
        int j;
        scanf("%d%d", &a, &b);
        ma = a; mb = b;

        i = (sizeof (int) * 8) - 1;
        j = 1 << i;

        ((a & j) && flipnum(&a, &a_neg));

        ((b & j) && flipnum(&b, &b_neg));

        j = 1 << (i - 1);

        recursive_check(j);

        (!stop && printf("numbers are same..\n"));
    }
#包括
#包括
int a,b,i,ma,mb,a_neg,b_neg,stop;
int flipnum(int*num,int*is_neg){
*num=~(*num)+1;
*is_neg=1;
返回0;
}
int print_num1(){
返回((a_neg&&printf(“较大的数字%d\n”,mb))||
printf(“较大的数字%d\n”,ma));
}
int print_num2(){
返回((b_neg&&printf(“较大的数字%d\n”,ma))||
printf(“较大的数字%d\n”,mb));
}
整数检查数m1(整数j){
返回((a&j)和打印num1());
}
内部检查\u num2(内部j){
返回((b&j)和打印(num2());
}
int递归检查(int j){
(a&j)^(b&j)&&&(check_num1(j)| check_num2(j))&&&(stop=1,j=0);
返回(!停止和(j=j>>1)和递归检查(j));
}
int main(){
int j;
scanf(“%d%d”、&a和&b);
ma=a;mb=b;
i=(sizeof(int)*8)-1;

j=1要将
001xxxxx
转换为
00100000
,首先执行:

x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
(这是针对8位的;要将其扩展到32位,请在序列开始处添加8和16的移位)

这只剩下
#include <limits.h>
static const int INT_NEG = (1 << ((sizeof(int) * CHAR_BIT) - 1));
void test_isgt(int a, int b)
{
    fprintf(stdout,
        "%11d > %11d = %d : %d %s\n",
        a, b,
        isgt(a, b), (a > b),
        isgt(a, b) != (a>b) ? "BAD!" : "OK!");
}
         33 >           0 = 1 : 1 OK!
        -33 >           0 = 0 : 0 OK!
          0 >          33 = 0 : 0 OK!
          0 >         -33 = 1 : 1 OK!
          0 >           0 = 0 : 0 OK!
         33 >          33 = 0 : 0 OK!
        -33 >         -33 = 0 : 0 OK!
         -5 >         -33 = 1 : 1 OK!
        -33 >          -5 = 0 : 0 OK!
-2147483647 >  2147483647 = 0 : 0 OK!
 2147483647 > -2147483647 = 1 : 1 OK!
 2147483647 >  2147483647 = 0 : 0 OK!
 2147483647 >           0 = 1 : 1 OK!
          0 >  2147483647 = 0 : 0 OK!
    #include<unistd.h>
    #include<stdio.h>
    int a, b, i, ma, mb, a_neg, b_neg, stop;

    int flipnum(int *num, int *is_neg) {
        *num = ~(*num) + 1;
        *is_neg = 1;

        return 0;
    }

    int print_num1() {
        return ((a_neg && printf("bigger number %d\n", mb)) ||
             printf("bigger number %d\n", ma));
    }

    int print_num2() {
        return ((b_neg && printf("bigger number %d\n", ma)) ||
             printf("bigger number %d\n", mb));
    }

    int check_num1(int j) {
        return ((a & j) && print_num1());
    }

    int check_num2(int j) {
        return ((b & j) && print_num2());
    }

    int recursive_check (int j) {
        ((a & j) ^ (b & j)) && (check_num1(j) || check_num2(j))  && (stop = 1, j = 0);

        return(!stop && (j = j >> 1) && recursive_check(j));
    }

    int main() {
        int j;
        scanf("%d%d", &a, &b);
        ma = a; mb = b;

        i = (sizeof (int) * 8) - 1;
        j = 1 << i;

        ((a & j) && flipnum(&a, &a_neg));

        ((b & j) && flipnum(&b, &b_neg));

        j = 1 << (i - 1);

        recursive_check(j);

        (!stop && printf("numbers are same..\n"));
    }
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
x ^= x >> 1;
int isGt(int a, int b)
{
    int diff = a ^ b;
    diff |= diff >> 1;
    diff |= diff >> 2;
    diff |= diff >> 4;
    diff |= diff >> 8;
    diff |= diff >> 16;

    //1+ on GT, 0 otherwise.
    diff &= ~(diff >> 1) | 0x80000000;
    diff &= (a ^ 0x80000000) & (b ^ 0x7fffffff);

    //flatten back to range of 0 or 1.
    diff |= diff >> 1;
    diff |= diff >> 2;
    diff |= diff >> 4;
    diff |= diff >> 8;
    diff |= diff >> 16;
    diff &= 1;

    return diff;
}