使用按位运算检查变量中位的最快方法是什么?
What is the fastest way to check bits in variable using bitwise operations?
例如我有短(2 字节 = 16 位)变量:(在我的项目中这是 00、01 和 10 的序列)
0001010101101001 = 0001.0101|0110.1001
我想检查这个变量是否包含位序列,例如我需要“01010101”(这是 4 x 01)。
最快的检查方法是什么?
我找到了一些解决方案,但我确信存在更简单、更快速的解决方案。
(pseudocode)
var = 0001010101101001;
need = 0000000001010101;
for(int i=0;i<4;i++)
{
if(var&need==need)
return 1;
else
var = var >> 2;
}
或:
(pseudocode)
var = 0001010101101001;
need1 = 0000000001010101;
need2 = 0000000101010100;
need3 = 0000010101010000;
need4 = 0001010101000000;
need5 = 0101010100000000;
if(var&need1==need1) return 1;
if(var&need2==need2) return 1;
if(var&need3==need3) return 1;
if(var&need4==need4) return 1;
if(var&need5==need5) return 1;
else return 0;
还有一个方法:
var &= 0101010101010101
var &= var >> 2
var &= var >> 4
return var != 0
奇数位无关紧要,因此在第一步中将其删除。
然后将每 4 个相邻的 "pieces"(每个 2 位)分两步进行 AND 运算,首先是将每个片段与直接位于其左侧的片段相结合,然后通过在距离上做同样的事情来复合2 件。所以结果是 4 个“01”序列是否从该位置开始的掩码。
最后检查该掩码中是否设置了任何位。
你的第一个解决方案很好:
for (int Count = 0; Count < 4; Count++)
{
if ((Var & Need) == Need)
Found = true;
else
Var = (UInt16)(Var >> 2);
}
实际上我把事情弄复杂了而不是简化了。
这是使用遮罩的替代解决方案。
using System;
public class Program
{
public static void Main()
{
UInt16 Var = 0x1569; //0001010101101001 0x1569
UInt16 Need = 0x5A; //0000000001011010 0x5A
//0000000001010101 0x55
//0000000001010110 0x56
UInt16[] Mask = { 0x00FF, 0x03FC, 0x0FF0, 0x3FC0, 0xFF00 };
bool Found = false;
for (int Count = 0; Count < 4; Count++)
Found |= (((Var & Mask[Count]) ^ (Need << (Count + Count))) == 0);
Console.WriteLine(Found);
}
}
例如我有短(2 字节 = 16 位)变量:(在我的项目中这是 00、01 和 10 的序列)
0001010101101001 = 0001.0101|0110.1001
我想检查这个变量是否包含位序列,例如我需要“01010101”(这是 4 x 01)。
最快的检查方法是什么? 我找到了一些解决方案,但我确信存在更简单、更快速的解决方案。
(pseudocode)
var = 0001010101101001;
need = 0000000001010101;
for(int i=0;i<4;i++)
{
if(var&need==need)
return 1;
else
var = var >> 2;
}
或:
(pseudocode)
var = 0001010101101001;
need1 = 0000000001010101;
need2 = 0000000101010100;
need3 = 0000010101010000;
need4 = 0001010101000000;
need5 = 0101010100000000;
if(var&need1==need1) return 1;
if(var&need2==need2) return 1;
if(var&need3==need3) return 1;
if(var&need4==need4) return 1;
if(var&need5==need5) return 1;
else return 0;
还有一个方法:
var &= 0101010101010101
var &= var >> 2
var &= var >> 4
return var != 0
奇数位无关紧要,因此在第一步中将其删除。
然后将每 4 个相邻的 "pieces"(每个 2 位)分两步进行 AND 运算,首先是将每个片段与直接位于其左侧的片段相结合,然后通过在距离上做同样的事情来复合2 件。所以结果是 4 个“01”序列是否从该位置开始的掩码。
最后检查该掩码中是否设置了任何位。
你的第一个解决方案很好:
for (int Count = 0; Count < 4; Count++)
{
if ((Var & Need) == Need)
Found = true;
else
Var = (UInt16)(Var >> 2);
}
实际上我把事情弄复杂了而不是简化了。
这是使用遮罩的替代解决方案。
using System;
public class Program
{
public static void Main()
{
UInt16 Var = 0x1569; //0001010101101001 0x1569
UInt16 Need = 0x5A; //0000000001011010 0x5A
//0000000001010101 0x55
//0000000001010110 0x56
UInt16[] Mask = { 0x00FF, 0x03FC, 0x0FF0, 0x3FC0, 0xFF00 };
bool Found = false;
for (int Count = 0; Count < 4; Count++)
Found |= (((Var & Mask[Count]) ^ (Need << (Count + Count))) == 0);
Console.WriteLine(Found);
}
}