我有一个字节,特别是字节数组中的一个字节,该字节数组是通过另一设备发送的UDP传入的。该字节存储设备中8个继电器的开/关状态。
如何获得所述字节中特定位的值?理想情况下,扩展方法看起来最优雅,而返回布尔值对我来说最有意义。
public static bool GetBit(this byte b, int bitNumber)
{
//black magic goes here
}
我有一个字节,特别是字节数组中的一个字节,该字节数组是通过另一设备发送的UDP传入的。该字节存储设备中8个继电器的开/关状态。
如何获得所述字节中特定位的值?理想情况下,扩展方法看起来最优雅,而返回布尔值对我来说最有意义。
public static bool GetBit(this byte b, int bitNumber)
{
//black magic goes here
}
Answers:
简单。使用按位与将您的数字与2 ^ bitNumber的值进行比较,可以通过移位将其便宜地计算出来。
//your black magic
var bit = (b & (1 << bitNumber-1)) != 0;
编辑:添加更多的细节,因为有很多类似的答案而没有解释:
逐位AND使用AND连接逐位比较每个数字,以产生一个数字,该数字是在该位置的第一位和第二位都被设置的位的组合。这是“半字节”中AND逻辑的逻辑矩阵,显示了按位AND的操作:
0101
& 0011
----
0001 //Only the last bit is set, because only the last bit of both summands were set
在您的情况下,我们将您传递的数字与仅包含您要查找的位的数字进行比较。假设您正在寻找第四位:
11010010
& 00001000
--------
00000000 //== 0, so the bit is not set
11011010
& 00001000
--------
00001000 //!= 0, so the bit is set
移位确实是我们想要比较的数字,听起来像是:将数字表示为一组位,然后将这些位左移或右移一定数量。由于这些是二进制数,因此每个位的位数都是比其右边的位数大一的2的幂,因此向左移位等于对每个移位的位置将数字加倍一次,即等于将该数字乘以2 ^ x。在您的示例中,寻找第四位,我们执行:
1 (2^0) << (4-1) == 8 (2^3)
00000001 << (4-1) == 00001000
现在,您知道它是如何完成的,在低层发生了什么以及为什么起作用。
虽然阅读和理解Josh的回答很好,但是使用Microsoft为此目的提供的类可能会更高兴:System.Collections.BitArray 在.NET Framework的所有版本中都可用。
这个
public static bool GetBit(this byte b, int bitNumber) {
return (b & (1 << bitNumber)) != 0;
}
我认为应该这样做。
另一种方式:)
return ((b >> bitNumber) & 1) != 0;
((2 >> 1)&1)是1和((2 >> 0)&1)是0因为2是00000010
使用BitArray类并按照OP的建议使用扩展方法:
public static bool GetBit(this byte b, int bitNumber)
{
System.Collections.BitArray ba = new BitArray(new byte[]{b});
return ba.Get(bitNumber);
}
该方法是使用另一个字节以及按位与,以屏蔽目标位。
我在这里的类中使用约定,其中“ 0”是最高有效位,“ 7”是最低有效位。
public static class ByteExtensions
{
// Assume 0 is the MSB andd 7 is the LSB.
public static bool GetBit(this byte byt, int index)
{
if (index < 0 || index > 7)
throw new ArgumentOutOfRangeException();
int shift = 7 - index;
// Get a single bit in the proper position.
byte bitMask = (byte)(1 << shift);
// Mask out the appropriate bit.
byte masked = (byte)(byt & bitMask);
// If masked != 0, then the masked out bit is 1.
// Otherwise, masked will be 0.
return masked != 0;
}
}
试试下面的代码。与其他帖子的不同之处在于,您可以使用掩码(field)设置/获取多个位。例如,第4位的掩码可以是1 << 3或0x10。
public int SetBits(this int target, int field, bool value)
{
if (value) //set value
{
return target | field;
}
else //clear value
{
return target & (~field);
}
}
public bool GetBits(this int target, int field)
{
return (target & field) > 0;
}
**范例**
bool is_ok = 0x01AF.GetBits(0x10); //false
int res = 0x01AF.SetBits(0x10, true);
is_ok = res.GetBits(0x10); // true
var bit = (b & (1 << bitNumber-1)) != 0;