9

我有这些可能的位标志。

1, 2, 4, 8, 16, 64, 128, 256, 512, 2048, 4096, 16384, 32768, 65536

所以每个数字就像服务器端的真/假语句。因此,如果前 3 项,并且只有前 3 项在服务器端被标记为“真”,则 Web 服务将返回 7。或者如果以上 14 项都为真,我仍然会从Web 服务是所有这些数字的总和。

处理我找回的号码以找出哪些项目被标记为“真实”的最佳方法是什么?

4

5 回答 5

7

使用位掩码运算符。在 C 语言中:

 X & 8

如果设置了“8”位,则为真。

您可以枚举位掩码,并计算设置了多少。

如果确实是整个单词包含位的情况,并且您想简单地计算设置了多少位,那么您实际上需要一个“人口计数”。获得人口计数的绝对最快的方法是执行通常在您的机器指令集中可用的本机“popcnt”。

如果您不关心空间,则可以设置一个数组countedbits[...],并使用预先计算的位数来索引您的值。然后单个内存访问计算您的位数。

经常使用的只是 计算位数的简单“位旋转代码” :

(克尼根的方法):

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; c++)
{
  v &= v - 1; // clear the least significant bit set
}

(并行位求和,32 位)

v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count

如果您以前没有看过这些小技巧,那么您一定会大吃一惊。

PHP,很有趣,可能会用这种算法做一些有趣的事情。

于 2010-05-07T21:58:17.723 回答
6
if (7 & 1) { // if bit 1 is set in returned number (7)

}
于 2010-05-07T22:00:36.610 回答
5

认为这个问题很老可能会帮助别人。我把数字放在二进制中,因为它更容易理解。该代码尚未经过测试,但希望逻辑清晰。该代码是特定于 PHP 的。

define('FLAG_A', 0b10000000000000);  
define('FLAG_B', 0b01000000000000);
define('FLAG_C', 0b00100000000000);
define('FLAG_D', 0b00010000000000);
define('FLAG_E', 0b00001000000000);
define('FLAG_F', 0b00000100000000);
define('FLAG_G', 0b00000010000000);
define('FLAG_H', 0b00000001000000);
define('FLAG_I', 0b00000000100000);
define('FLAG_J', 0b00000000010000);
define('FLAG_K', 0b00000000001000);
define('FLAG_L', 0b00000000000100);
define('FLAG_M', 0b00000000000010);
define('FLAG_N', 0b00000000000001);

function isFlagSet($Flag,$Setting,$All=false){
  $setFlags = $Flag & $Setting;
  if($setFlags and !$All) // at least one of the flags passed is set
     return true;
  else if($All and ($setFlags == $Flag)) // to check that all flags are set
     return true;
  else
     return false;
}

用法:

if(isFlagSet(FLAG_A,someSettingsVariable)) // eg: someSettingsVariable = 0b01100000000010

if(isFlagSet(FLAG_A | FLAG_F | FLAG_L,someSettingsVariable)) // to check if atleast one flag is set

if(isFlagSet(FLAG_A | FLAG_J | FLAG_M | FLAG_D,someSettingsVariable, TRUE)) // to check if all flags are set
于 2015-05-21T07:54:10.620 回答
1

一种方法是遍历您的数字,将其左移(即除以 2)并使用 & 操作数将第一位与 1 进行比较。

于 2010-05-07T22:05:26.457 回答
1

由于 php 代码没有明确的答案,我添加了这个工作示例:

// returns array of numbers, so for 7 returns array(1,2,4), etc..

function get_bits($decimal) {
  $scan = 1;
  $result = array();
  while ($decimal >= $scan){
    if ($decimal & $scan) $result[] = $scan;
    $scan<<=1; 
  }
  return $result;
}
于 2016-09-15T18:59:51.030 回答