程序计算在c中设置的位数

gj3fmq9x  于 2023-10-16  发布在  其他
关注(0)|答案(8)|浏览(124)

我试着在C中计算一个整数值中设置的位数。但对于某些值,它显示正确的位集计数,而对于某些值,它则不是。
PFB程序代码

int main()
{
    int a = 512, i = 0, j = 1, count = 0, k = 0;

    for (i = 0; i < 31; i++)
    {
        if (k = a & j)
        {
            count++;
            j = j << 1;
        }
    }
    printf("the total bit set count is %d", count);
}

设置位值计数512的输出显示为零,如果使用的值为511,则计数显示为9。
请帮我修改一下程序。

dluptydi

dluptydi1#

斯坦福大学有一页介绍了实现常见位旋转操作的不同方法。他们列出了5种不同的算法来计算位集,所有这些都有C示例。
https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
最简单的实现:

unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v

for (c = 0; v; v >>= 1)
{
  c += v & 1;
}
xe55xuns

xe55xuns2#

如果使用的是gcc/clang编译器,可以使用内置函数**_builtin_popcount**

unsigned int user_input = 100
int count = __builtin_popcount(n); // count == 3

当我不寻找跨平台,我会使用这个功能,因为它的高度优化。

kiayqfof

kiayqfof3#

一般来说,你会在一个无符号整数中计算位数。原因是,您通常会检查寄存器或掩码中的位设置。有符号整数是用two’s-complement表示的,我想不出你为什么要在有符号整数中计算集合位(如果你确实想要这样做,你会感兴趣的)。
请注意,在C中,如果数字为负,则向右或向左移动有符号整数是实现定义的行为。来自C标准第6.5.7节:
. E1 << E2的结果是E1左移E2比特位置;.如果E1具有带符号类型和非负值,并且E1 << E2在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。
E1 >> E2的结果是E1右移E2位位置。.如果E1具有带符号类型和负值,则结果值是实现定义的.
如果你想在一个任意大小的unsigned整数中计算1的个数,你可以使用this example

#include <stdio.h>

int main(void) {
   unsigned int value = 1234;
   unsigned int ones = 0;
   while(value > 0) {
      ones += value & 0x1;
      value >>= 1;
   }
   printf("#Ones = %u", ones);
}

在这个例子中,value可以是unsigned char,unsigned long,任何unsigned integer类型。
注意:不要移动有符号值或浮点数/双精度数。

oxosxuxt

oxosxuxt4#

您可以使用除法/和模%运算符来检查整数中设置的位。

int main()
{
    int a = 512, count = 0;

    while(a != 0)
    {
        if(a % 2 == 1)
        {
            count++;
        }
        a /= 2;
    }
    printf("The total bit set is %d", count);
}
rggaifut

rggaifut5#

您正在检查a&j的值,如果a&j为0,则不做任何其他操作,而是重试。
你的j-bitshift需要在if-then之外。

gopyfrb3

gopyfrb36#

你犯了几个错误:

for(i=0;i<32;i++) // <<< this should be 32, not 31
{
    if(k=a&j)
    {
        count++;
    }
    j=j<<1;       // <<< this needs to be outside the if block
}

请注意,与其使用硬编码值32表示int中的位数,不如这样做:

for(i=0;i<sizeof(int)*CHAR_BIT;i++)

这样,如果int的大小是例如,代码仍然可以工作。16位或64位。

c90pui9n

c90pui9n7#

虽然严格来说这不是C语言,但你可以使用内联汇编来调用POPCNT x86操作:

// GCC syntax
unsigned a = 1234;
unsigned int count;
__asm__( 
    "  POPCNT %0, %1\n"
    :"=r" (count)
    :"r" (a)
);
return count;

根据this benchmark,像在idok's answer中那样调用__builtin_popcount与上面的代码一样快,它们都比任何其他C实现快得多。您也可以查看链接的repo以获取其他解决方案。

xv8emn3q

xv8emn3q8#

#include<stdio.h>
#include<conio.h>

int rem, binary = 0;
unsigned int

countSetBits (unsigned int n){

    unsigned int count = 0;

    while (n){
        count += n & 1;
        n >>= 1;
    }

    printf ("\n\t Number of  1's  in the binary number is : %d",count);
}

int dec_bin (int n){

    int i=1;

    while (n != 0){
        rem = n % 2;
        n = n / 2;
        binary = binary + (rem * i);
        i = i * 10;
    }

    printf("\n\t The converted Binary Equivalent is : %d",binary);
}

int main(){  
    int i = 0;

    printf ("\n\t Enter the Decimal Nummber: ");

    scanf ("%d", &i);

    int n= i;
    dec_bin(n);
    countSetBits (i);
    return 0;
}

相关问题