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

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

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

  1. int main()
  2. {
  3. int a = 512, i = 0, j = 1, count = 0, k = 0;
  4. for (i = 0; i < 31; i++)
  5. {
  6. if (k = a & j)
  7. {
  8. count++;
  9. j = j << 1;
  10. }
  11. }
  12. printf("the total bit set count is %d", count);
  13. }

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

dluptydi

dluptydi1#

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

  1. unsigned int v; // count the number of bits set in v
  2. unsigned int c; // c accumulates the total bits set in v
  3. for (c = 0; v; v >>= 1)
  4. {
  5. c += v & 1;
  6. }
xe55xuns

xe55xuns2#

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

  1. unsigned int user_input = 100
  2. 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

  1. #include <stdio.h>
  2. int main(void) {
  3. unsigned int value = 1234;
  4. unsigned int ones = 0;
  5. while(value > 0) {
  6. ones += value & 0x1;
  7. value >>= 1;
  8. }
  9. printf("#Ones = %u", ones);
  10. }

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

展开查看全部
oxosxuxt

oxosxuxt4#

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

  1. int main()
  2. {
  3. int a = 512, count = 0;
  4. while(a != 0)
  5. {
  6. if(a % 2 == 1)
  7. {
  8. count++;
  9. }
  10. a /= 2;
  11. }
  12. printf("The total bit set is %d", count);
  13. }
rggaifut

rggaifut5#

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

gopyfrb3

gopyfrb36#

你犯了几个错误:

  1. for(i=0;i<32;i++) // <<< this should be 32, not 31
  2. {
  3. if(k=a&j)
  4. {
  5. count++;
  6. }
  7. j=j<<1; // <<< this needs to be outside the if block
  8. }

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

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

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

c90pui9n

c90pui9n7#

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

  1. // GCC syntax
  2. unsigned a = 1234;
  3. unsigned int count;
  4. __asm__(
  5. " POPCNT %0, %1\n"
  6. :"=r" (count)
  7. :"r" (a)
  8. );
  9. return count;

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

xv8emn3q

xv8emn3q8#

  1. #include<stdio.h>
  2. #include<conio.h>
  3. int rem, binary = 0;
  4. unsigned int
  5. countSetBits (unsigned int n){
  6. unsigned int count = 0;
  7. while (n){
  8. count += n & 1;
  9. n >>= 1;
  10. }
  11. printf ("\n\t Number of 1's in the binary number is : %d",count);
  12. }
  13. int dec_bin (int n){
  14. int i=1;
  15. while (n != 0){
  16. rem = n % 2;
  17. n = n / 2;
  18. binary = binary + (rem * i);
  19. i = i * 10;
  20. }
  21. printf("\n\t The converted Binary Equivalent is : %d",binary);
  22. }
  23. int main(){
  24. int i = 0;
  25. printf ("\n\t Enter the Decimal Nummber: ");
  26. scanf ("%d", &i);
  27. int n= i;
  28. dec_bin(n);
  29. countSetBits (i);
  30. return 0;
  31. }
展开查看全部

相关问题