簡體   English   中英

計算c中設置的位數的程序

[英]Program to count the number of bits set in c

我試圖計算 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 countis %d",count);
}

512 的設置位值計數的輸出顯示為零,如果使用的值是 511,則計數顯示為 9。

請幫我更正程序。

斯坦福大學有一頁介紹了實現常見位處理操作的不同方法。 他們列出了 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;
}

通常,您會計算無符號整數中的位數。 例如,原因是您通常檢查寄存器或掩碼中設置的位。 有符號整數使用二進制補碼表示,我想不出為什么您要計算有符號整數中的設置位(如果您確實想要這個,我會感興趣為什么)。

請注意,在 C 中,如果數字為負,則右移或左移有符號整數是實現定義的行為 來自 C 標准 sectn 6.5.7:

... E1 << E2 的結果是 E1 左移 E2 位位置; ... 如果 E1 具有有符號類型和非負值,並且 E1 << E2 在結果類型中可表示,那么這就是結果值; 否則,行為未定義。

E1 >> E2 的結果是 E1 右移 E2 位位置。 ...如果 E1 具有有符號類型和負值,則結果值是實現定義的...

如果你想在任意大小的無符號整數中計算 1,你可以使用這個例子

#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、任何無符號整數類型...

注意:不要移動有符號值或浮點數/雙精度數。

如果你使用 gcc/clang 編譯器,你可以使用內置函數__builtin_popcount

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

當我不尋找跨平台時,我會使用此功能,因為它經過了高度優化。

您可以使用除法/和模%運算符來檢查設置在整數中的位。

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);
}

你有幾個錯誤:

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
}

請注意,與其對int的位數使用硬編碼值 32,不如這樣做:

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

這樣,如果int的大小為 16 位或 64 位,代碼仍然可以工作。

您正在檢查a&j的值,如果a&j為 0,那么您除了重試之外什么都不做。

您的j -bitshift 需要在 if-then 之外。

#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;
}

雖然嚴格來說這不是 C,但您可以使用內聯匯編來調用POPCNT x86 操作:

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

根據這個基准,在idok 的回答中調用__builtin_popcount與上面的代碼一樣快,而且它們都比任何其他 C 實現快得多。 您還可以檢查鏈接的存儲庫以獲取其他解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM