我有一个字节,特别是来自字节数组的一个字节,它通过从另一个设备发送的UDP进入。该字节存储器件中8个继电器的开/关状态。
如何获取所述字节中特定位的值?理想情况下,扩展方法看起来最优雅,返回bool对我来说最有意义。
public static bool GetBit(this byte b, int bitNumber)
{
//black magic goes here
}
答案 0 :(得分:152)
易。使用按位AND将您的数字与值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 ^ x的。在您的示例中,查找第四位,我们执行:
1 (2^0) << (4-1) == 8 (2^3)
00000001 << (4-1) == 00001000
现在你知道它是如何完成的,在低级别发生了什么,以及它为什么会起作用。
答案 1 :(得分:49)
虽然阅读和理解Josh的答案是好的,但是你可能会更乐意使用Microsoft为此目的提供的类:System.Collections.BitArray它可以在所有版本的.NET Framework中使用。
答案 2 :(得分:36)
此
public static bool GetBit(this byte b, int bitNumber) {
return (b & (1 << bitNumber)) != 0;
}
我认为应该这样做。
答案 3 :(得分:9)
另一种方式:)
return ((b >> bitNumber) & 1) != 0;
答案 4 :(得分:6)
使用BitArray类并将扩展方法设为OP建议:
public static bool GetBit(this byte b, int bitNumber)
{
System.Collections.BitArray ba = new BitArray(new byte[]{b});
return ba.Get(bitNumber);
}
答案 5 :(得分:4)
试试这个:
return (b & (1 << bitNumber))>0;
答案 6 :(得分:4)
这比0.1毫秒更快。
return (b >> bitNumber) & 1;
答案 7 :(得分:3)
该方法是使用另一个字节以及按位AND来屏蔽目标位。
我在我的班级使用惯例,其中“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;
}
}
答案 8 :(得分:3)
尝试以下代码。与其他帖子的不同之处在于您可以使用掩码(field
)设置/获取多个位。例如,第4位的掩码可以是1 <&lt; 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
答案 9 :(得分:2)
这个网站有多个实现如何从C#中的一个字节获取一点。它对此也有很好的解释。 http://bytes.com/topic/c-sharp/answers/505085-reading-bits-byte-file
答案 10 :(得分:1)
[Flags]
enum Relays : byte
{
relay0 = 1 << 0,
relay1 = 1 << 1,
relay2 = 1 << 2,
relay3 = 1 << 3,
relay4 = 1 << 4,
relay5 = 1 << 5,
relay6 = 1 << 6,
relay7 = 1 << 7
}
public static bool GetRelay(byte b, Relays relay)
{
return (Relays)b.HasFlag(relay);
}