121

I have a byte, specifically one byte from a byte array which came in via UDP sent from another device. This byte stores the on/off state of 8 relays in the device.

How do I get the value of a specific bit in said byte? Ideally an extension method would look the most elegant and returning a bool would make the most sense to me.

public static bool GetBit(this byte b, int bitNumber)
{
 //black magic goes here
}
asked Jan 31, 2011 at 17:48
0

11 Answers 11

210

Easy. Use a bitwise AND to compare your number with the value 2^bitNumber, which can be cheaply calculated by bit-shifting.

//your black magic
var bit = (b & (1 << bitNumber-1)) != 0;

EDIT: To add a little more detail because there are a lot of similar answers with no explanation:

A bitwise AND compares each number, bit-by-bit, using an AND join to produce a number that is the combination of bits where both the first bit and second bit in that place were set. Here's the logic matrix of AND logic in a "nibble" that shows the operation of a bitwise AND:

 0101
& 0011
 ----
 0001 //Only the last bit is set, because only the last bit of both summands were set

In your case, we compare the number you passed with a number that has only the bit you want to look for set. Let's say you're looking for the fourth bit:

 11010010
& 00001000
 --------
 00000000 //== 0, so the bit is not set
 11011010
& 00001000
 --------
 00001000 //!= 0, so the bit is set

Bit-shifting, to produce the number we want to compare against, is exactly what it sounds like: take the number, represented as a set of bits, and shift those bits left or right by a certain number of places. Because these are binary numbers and so each bit is one greater power-of-two than the one to its right, bit-shifting to the left is equivalent to doubling the number once for each place that is shifted, equivalent to multiplying the number by 2^x. In your example, looking for the fourth bit, we perform:

 1 (2^0) << (4-1) == 8 (2^3)
00000001 << (4-1) == 00001000

Now you know how it's done, what's going on at the low level, and why it works.

answered Jan 31, 2011 at 17:54

6 Comments

Because of missing braces (operator precedence) this code does not compile, it must be var bit = (b & (1 << bitNumber-1)) != 0;
this delivers a result desphased by one bit... the correct solution should be return (b & (1 << bitNumber)) != 0;
I find it confusing that both OP and answer start counting from 1. Why not starting bitnumber from 0?
I found it confused as well with bitNumber-1. We are all familiar with bit0, bit1, and so on. And why there is a need of !=0 at the end? Code below is simplest and fastest? return (b >> bitNumber) & 1;
@BachPhi - Your expression produces an integer value. In C#, integers cannot be implicitly cast to booleans. Other (most?) C-style languages do allow boolean evaluation of integer values, but the question is specifically tagged C#, and in that language you either need an explicit cast to bool or a comparison operation that evaluates to a boolean. !=0 is both more concise than (bool)(...) and more intuitively self-documenting regarding author intent.
|
62

While it's good to read and understand Josh's answer, you'll probably be happier using the class Microsoft provided for this purpose: System.Collections.BitArray It's available in all versions of .NET Framework.

Eonasdan
7,8019 gold badges60 silver badges85 bronze badges
answered Jan 31, 2011 at 17:56

4 Comments

This is fabulous but I believe Josh's solution is much faster and more efficient.
@user2332868: the JIT compiler does specially recognize calls to certain library functions and generate efficient code, but I have no idea if these particular functions get the love.
well to be sure you can do the same as Josh but in pure inline assembly. But sadly I only program in NASM assembly and don't know about the assembly C# compiles into :(.
IMHO this kills performance for such a simple task. Using the bitwise operator alternative also gives you a tool that you can use it in almost any language =)
44

This

public static bool GetBit(this byte b, int bitNumber) {
 return (b & (1 << bitNumber)) != 0;
}

should do it, I think.

answered Jan 31, 2011 at 17:53

Comments

34

This is works faster than 0.1 milliseconds.

return (b >> bitNumber) & 1;
answered May 22, 2015 at 12:51

1 Comment

This is the fastest method.
11

another way of doing it :)

return ((b >> bitNumber) & 1) != 0;
answered Jan 31, 2011 at 17:59

3 Comments

This won't work: byte b = 1; return ((b >> 1) & 1) != 0 (it's equals to 0)
Hmmm... I don't get you. If byte b = 1, bit at position 0 is 1, given by (b>>0)&1, and bit at any position greater or equal than 1 is 0, given by (b>>n)&1 where n>=1 as well
I don't believe his does that at all @DavideAndrea, the comment posted by Rafael assumes the right-most bit is bit 1, but PierrOz's code is for when the right most bit is bit 0. If b was 2, then ((2 >> 1)&1) is 1 and ((2 >> 0)&1) is 0 because 2 is 00000010
9

Using BitArray class and making an extension method as OP suggests:

public static bool GetBit(this byte b, int bitNumber)
{
 System.Collections.BitArray ba = new BitArray(new byte[]{b});
 return ba.Get(bitNumber);
}
answered Feb 9, 2013 at 15:18

4 Comments

No, please don't create and throw away a BitArray for each bit test.
@BenVoigt, it's an extension method on a byte per OP request. Where do you recommend storing the BitArray instance?
You push back against the request and say, don't call it like a method on the byte, call it on the BitArray. Maybe the byte variable can completely go away.
If you're looking to get the nth bit of a byte you're most likely looking for performance, and this kills it. Otherwise you could always do other unnecessary things like Convert.ToString(num,2)[bitNumber] and get it too.
5

try this:

return (b & (1 << bitNumber))>0;
answered Jan 31, 2011 at 17:53

Comments

4

The method is to use another byte along with a bitwise AND to mask out the target bit.

I used convention from my classes here where "0" is the most significant bit and "7" is the least.

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;
 }
}
answered Jan 31, 2011 at 17:56

Comments

4

Try the code below. The difference with other posts is that you can set/get multiple bits using a mask (field). The mask for the 4th bit can be 1<<3, or 0x10, for example.

 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;
 }

** Example **

 bool is_ok = 0x01AF.GetBits(0x10); //false
 int res = 0x01AF.SetBits(0x10, true);
 is_ok = res.GetBits(0x10); // true
answered Jan 31, 2011 at 18:02

Comments

3
[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);
}
answered Apr 18, 2018 at 9:48

Comments

0

In unity class. It was passed.

using System;
 public static bool GetBit(byte b, int bitNumber)
 {
 return Convert.ToBoolean((b >> bitNumber - 1) & 1);
 }
answered Sep 14, 2023 at 10:50

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.