屏蔽时可以使用哪些逻辑操作来忽略不相关的位?
Which logical operations can I use to ignore irrelevant bits when masking?
上下文
假设我有一个包含 8 个布尔变量的系统模型。它们一起构成一个字节,可以表达我的系统的 128 种状态排列。让这个字节为stateByte
,其中每一位都是我的变量之一。
现在,假设我有一些可枚举的状态,例如:
public enum States
{
READY = 0b_0000_0001
OPERATING = 0b_0100_0000
FAULT = 0b_1000_0000
}
如果每个 States
都是离散的,我可以很容易地确定 States currentState = (States)stateByte
,但是我的问题是:
我的状态只依赖于特定位的一个子集,而不是整个字节。具体来说,根据状态的不同,有些位是无关紧要的。要使用伪符号,我有下面的场景,其中 x
表示一个不相关的位:
public enum States
{
READY = 0b_0000_0001 // Exactly this permutation
OPERATING = 0b_0100_0000 // Exactly this permutation
FAULT = 0b_1xxx_xxxx // Only bit 7 need be high to determine a fault
}
问题
如何使用逻辑位运算符(掩码)来仅从相关位枚举状态?
更多背景
对于那些质疑我为什么要尝试这样做或为什么我不能简单地使用阈值的细节的坚持者,请查看下面我正在集成的硬件的完整状态 table:
您可以使用二进制和运算符 &
来屏蔽值,例如只包含某些位:
0b_1xxx_xxxx & 0b_1000_0000 = 0b_1000_0000
0b_1xxx_xxxx & (1 << 7) = 0b_1000_0000
0b_1xxx_xxxx & States.Fault = 0b_1000_0000
如果您想经常访问某些位,您可以编写如下扩展方法:
public static boolean GetBit(this byte bitmask, int index) =>
((bitmask >> index) & 1) != 0;
0b_1xxx_xxxx.GetBit(7) = true
如果您想一次检查多个位,您可以使用一个模式来匹配您要检查的所有位,并将它们与另一个包含所有“正确”位和 0 的模式进行比较:
0b_x0xx_1000
& 0b_0100_1111 // Only look at bits 0-3 and 6
== 0b_0000_1000 // Check that bit 6 is 0, 3 is 1 and 0-2 are 0
// Other bits are 0 due to the logical and
如果标志解决方案有效,那么它会像这样完成:
[Flags]
public enum States
{
READY = 0b_0000_0001,
OPERATING = 0b_0100_0000,
FAULT = 0b_1000_0000
}
static void Main(string[] args)
{
var s = (States)5;
var check = s = States.FAULT | States.OPERATING;
}
上下文
假设我有一个包含 8 个布尔变量的系统模型。它们一起构成一个字节,可以表达我的系统的 128 种状态排列。让这个字节为stateByte
,其中每一位都是我的变量之一。
现在,假设我有一些可枚举的状态,例如:
public enum States
{
READY = 0b_0000_0001
OPERATING = 0b_0100_0000
FAULT = 0b_1000_0000
}
如果每个 States
都是离散的,我可以很容易地确定 States currentState = (States)stateByte
,但是我的问题是:
我的状态只依赖于特定位的一个子集,而不是整个字节。具体来说,根据状态的不同,有些位是无关紧要的。要使用伪符号,我有下面的场景,其中 x
表示一个不相关的位:
public enum States
{
READY = 0b_0000_0001 // Exactly this permutation
OPERATING = 0b_0100_0000 // Exactly this permutation
FAULT = 0b_1xxx_xxxx // Only bit 7 need be high to determine a fault
}
问题
如何使用逻辑位运算符(掩码)来仅从相关位枚举状态?
更多背景
对于那些质疑我为什么要尝试这样做或为什么我不能简单地使用阈值的细节的坚持者,请查看下面我正在集成的硬件的完整状态 table:
您可以使用二进制和运算符 &
来屏蔽值,例如只包含某些位:
0b_1xxx_xxxx & 0b_1000_0000 = 0b_1000_0000
0b_1xxx_xxxx & (1 << 7) = 0b_1000_0000
0b_1xxx_xxxx & States.Fault = 0b_1000_0000
如果您想经常访问某些位,您可以编写如下扩展方法:
public static boolean GetBit(this byte bitmask, int index) =>
((bitmask >> index) & 1) != 0;
0b_1xxx_xxxx.GetBit(7) = true
如果您想一次检查多个位,您可以使用一个模式来匹配您要检查的所有位,并将它们与另一个包含所有“正确”位和 0 的模式进行比较:
0b_x0xx_1000
& 0b_0100_1111 // Only look at bits 0-3 and 6
== 0b_0000_1000 // Check that bit 6 is 0, 3 is 1 and 0-2 are 0
// Other bits are 0 due to the logical and
如果标志解决方案有效,那么它会像这样完成:
[Flags]
public enum States
{
READY = 0b_0000_0001,
OPERATING = 0b_0100_0000,
FAULT = 0b_1000_0000
}
static void Main(string[] args)
{
var s = (States)5;
var check = s = States.FAULT | States.OPERATING;
}