在无符号 32 位整数中查找位位置

Posted

技术标签:

【中文标题】在无符号 32 位整数中查找位位置【英文标题】:Finding Bit Positions in an unsigned 32-bit integer 【发布时间】:2011-03-09 17:50:30 【问题描述】:

当他们谈论位位置时,我想我可能已经在我的 CS 课上睡着了,所以我希望有人能伸出援手。

我有一个无符号的 32 位整数(让我们使用值:28)

根据我正在阅读的一些文档,整数的值包含指定各种事物的标志。

标志中的位位置从 1(低位)到 32(高位)编号。 所有未定义的标志位都是保留的,必须设置为 0。

我有一个表格,显示标志的含义,数字 1-10 的含义。

我希望有人可以尝试向我解释这一切的含义以及如何根据位位置从 28 之类的数字中找到“标志”值。

谢谢

【问题讨论】:

【参考方案1】:

假设您有一个整数数组,并且您想要找到所有位置(32 位位置),这些位被集体设置,即对于特定位位置,您将通过考虑总共有多少设置位所有的整数。在这种情况下,您可以做的是检查每个 Integer 并标记其设置位位置:

// let arr[n] is an array of integers of size n.
int fq[33] = 0 // frequency array that will contain frequency of set bits at a particular position as 1 based indexing.
for(int i=0; i<n; i++) 
   int x = arr[i];
   int pos = 1; // bit position
   for(int i=1; i<=pow(2,32); i= i<<1)   // i is the bit mask for checking every position and will go till 2^32 because x is an integer.
      if(x & i) fq[pos]++;
      pos++;
   

【讨论】:

【参考方案2】:
// You can check the bit set positions of 32 bit integer.
// That's why the check is added "i != 0 && i <= val" to iterate till 
// the end bit position.
    void find_bit_pos(unsigned int val) 
            unsigned int i;
            int bit_pos;
            printf("%u::\n", val);
            for(i = 1, bit_pos = 1; i != 0 && i <= val; i <<= 1, bit_pos++)  
                    if(val & i)
                            printf("set bit pos: %d\n", bit_pos);
            
    

【讨论】:

【参考方案3】:

@invaliddata 的回答略有不同-

unsigned int tmp_bitmap = x;        
while (tmp_bitmap > 0) 
    int next_psn = __builtin_ffs(tmp_bitmap) - 1;
    tmp_bitmap &= (tmp_bitmap-1);
    printf("Flag: %d set\n", next_psn);

【讨论】:

【参考方案4】:

使用以 2 为底的 log 函数。在 python 中,它看起来像:

import math 

position = math.log(value, 2)

如果位置不是整数,则超过 1 位被设置为 1。

【讨论】:

【参考方案5】:

您可以只遍历设置的位,而不是循环遍历每个位,如果您希望位被稀疏设置,这会更快:

假设位域在(标量整数)变量域中。

while (field)
  temp = field & -field;  //extract least significant bit on a 2s complement machine
  field ^= temp;  // toggle the bit off
  //now you could have a switch statement or bunch of conditionals to test temp
  //or get the index of the bit and index into a jump table, etc.

当位域不限于单个数据类型的大小,而是可以是任意大小时,效果很好。在这种情况下,您可以一次提取 32 个(或任何您的寄存器大小)位,针对 0 进行测试,然后继续下一个字。

【讨论】:

【参考方案6】:

28 转换为二进制的 11100。这意味着第 1 位和第 2 位未设置,而第 3、4 和 5 位已设置。

几点:首先,任何真正习惯 C 的人通常都会从 0 开始编号,而不是 1。其次,您可以使用按位和运算符 (&amp;) 测试各个标志,如下所示:

#define flag1 1    //  1 = 00 0001
#define flag2 2    //  2 = 00 0010
#define flag3 4    //  4 = 00 0100
#define flag4 8    //  8 = 00 1000
#define flag5 16   // 16 = 01 0000
#define flag6 32   // 32 = 10 0000

if (myvalue & flag1)
    // flag1 was set

if (myvalue & flag4)
    // flag4 was set

等等。您还可以检查循环中设置了哪些位:

#include <stdio.h>

int main()  
    int myvalue = 28;
    int i, iter;

    for (i=1, iter=1; i<256; i<<=1, iter++)
        if (myvalue & i)
            printf("Flag: %d set\n", iter);
    return 0;

应该打印:

Flag: 3 set
Flag: 4 set
Flag: 5 set

【讨论】:

杰里,你关于二进制值的第一部分是有道理的,但是我对你发布的代码有点困惑......你也有 flag1、flag2 等项目指的是什么?当我输入你所拥有的东西时,我会得到设置了 4 和 8 的输出。不确定这是指什么,因为上面我们说设置了第 3、4 和 5 位 @kdbdallas:我在代码中添加了一些 cmets,希望使标志的含义更加明显。【参考方案7】:

要获得一个带有值01int 仅代表该整数中的nth 位,请使用:

int bitN = (value >> n) & 1;

但这通常不是您想要做的。一个更常见的成语是这样的:

int bitN = value & (1 << n);

在这种情况下,如果nth 位未设置,bitN 将为0,而在nth 位设置的情况下为非零。 (具体来说,只要设置了nth 位,就会出现任何值。)

【讨论】:

【参考方案8】:

假设flags 未签名...

int flag_num = 1;
while (flags != 0)

    if ((flags&1) != 0)
    
        printf("Flag %d set\n", flags);
    
    flags >>= 1;
    flag_num += 1;

如果flags 已签名,则应替换

flags >>= 1;

flags = (flags >> 1) & 0x7fffffff;

【讨论】:

以上是关于在无符号 32 位整数中查找位位置的主要内容,如果未能解决你的问题,请参考以下文章

如何从 32 位 R 整数中提取 4 位无符号整数?

如何在 C 中提取 32 位无符号整数的特定“n”位?

如何在 x86(32 位)程序集中将无符号整数转换为浮点数?

2021-10-22:颠倒二进制位。颠倒给定的 32 位无符号整数的二进制位。提示:请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不

将 4 个字节转换为无符号 32 位整数并将其存储在 long

AVX2 矢量化 256 位查找表(32 个无符号字符)