73

How to check if a certain bit in a byte is set?

bool IsBitSet(Byte b,byte nPos)
{
   return .....;
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Manjoor
  • 4,091
  • 10
  • 43
  • 67

12 Answers12

202

sounds a bit like homework, but:

bool IsBitSet(byte b, int pos)
{
   return (b & (1 << pos)) != 0;
}

pos 0 is least significant bit, pos 7 is most.

Mario F
  • 45,569
  • 6
  • 37
  • 38
12

Based on Mario Fernandez's answer, I thought why not have it in my toolbox as a handy extension method not limited to datatype, so I hope it's OK to share it here:

/// <summary>
/// Returns whether the bit at the specified position is set.
/// </summary>
/// <typeparam name="T">Any integer type.</typeparam>
/// <param name="t">The value to check.</param>
/// <param name="pos">
/// The position of the bit to check, 0 refers to the least significant bit.
/// </param>
/// <returns>true if the specified bit is on, otherwise false.</returns>
public static bool IsBitSet<T>(this T t, int pos) where T : struct, IConvertible
{
 var value = t.ToInt64(CultureInfo.CurrentCulture);
 return (value & (1 << pos)) != 0;
}

Note: Do not use for performance critical operations, as this method always converts to long.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • 7
    This is highly inefficient. Bit operations are very fast. Calling this conversion function is orders of magnitude slower. Alternative: define multiple, identical functions for different input types, like uint, byte, ulong. – cskwg Jan 26 '19 at 06:48
  • 1
    @cskwg If performance is your be-all-end-all, why are you using bytes over ints in the first place? – arkon Mar 14 '23 at 22:30
12

Equivalent to Mario F code, but shifting the byte instead of mask:

bool IsBitSet(byte b, int pos)
{
   return ((b >> pos) & 1) != 0;
}
kaalus
  • 4,475
  • 3
  • 29
  • 39
11

Here is the solution in words.

Left shift an integer with initial value 1 n times and then do an AND with the original byte. If the result is non-zero, bit is Set otherwise not. :)

Aamir
  • 14,882
  • 6
  • 45
  • 69
  • Ok. Byte of 3, test if bit 1 is set. So 1<<1 is 2. 2&3 isn't true. Fail. – spender Mar 12 '10 at 09:51
  • 1
    @spender: err, surely 2 and 3 is 2 (in binary 10 and 11 = 10) which is non-zero and therefore a true result. OK, C# doesn't let you do that like C/C++ does so you'd need a != 0 test. – Skizz Mar 12 '10 at 09:55
  • Perhaps the check should be for non-zero? afaik, non-zero ain't true. – spender Mar 12 '10 at 09:55
  • Yes the check should be for non-zero instead of true. My C++ background :) – Aamir Mar 12 '10 at 09:59
  • +1 I've always just googled this and ignored the solution. Reading your solution made me understand it (along with a pencil, some zeros, and some ones). Thanks. – Stephano Oct 14 '11 at 06:59
5

Right shift your input n bits down and mask with 1, then test whether you have 0 or 1.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
5

This also works (tested in .NET 4):

void Main()
{
    //0x05 = 101b
    Console.WriteLine(IsBitSet(0x05, 0)); //True
    Console.WriteLine(IsBitSet(0x05, 1)); //False
    Console.WriteLine(IsBitSet(0x05, 2)); //True
}

bool IsBitSet(byte b, byte nPos){
    return new BitArray(new[]{b})[nPos];
}
Brian Chavez
  • 8,048
  • 5
  • 54
  • 47
  • 12
    If you're bit fiddling, you're probably after performance. Doing it this way may feel more OO, but it's going to kill perf. – Drew Noakes Oct 31 '12 at 00:29
  • 4
    I'm not gonna downvote you or anything but if you're looking for performance then you shouldn't do this. – Gaspa79 Nov 03 '16 at 18:13
2

something like

return ((0x1 << nPos) & b) != 0
abatishchev
  • 98,240
  • 88
  • 296
  • 433
RedPaladin
  • 784
  • 2
  • 9
  • 18
1

If you want to check multiple bits for any byte length (byte, int, long, etc.) in one shot vs shifting and looping, you can try the extension method below on your bit numeric type of choice (ByteExtension, IntExtension, LongExtension, etc.)

   public static class ByteExtensions
   {
      /// <summary>
      /// Return true if the respective set bits in mask are set in b.  Otherwise return false.
      /// </summary>
      /// <param name="b">byte to evaluate</param>
      /// <param name="mask">byte where if a bit is 1, test that b is also a 1</param>
      /// <returns>Return true if the respective set bits in mask are set in b.  Otherwise return false.</returns>
      public static bool AreBitsSet(this byte b, byte mask) => (b & mask) == mask;
      /// <summary>
      /// Return true if the respective set bits in value are cleared in b.  Otherwise return false.
      /// </summary>
      /// <param name="b">byte to evaluate</param>
      /// <param name="value">byte where if a bit is 1, test that b is also a 1</param>
      /// <returns>True if the respective set bits in value are cleared in b.  Otherwise return false.</returns>
      public static bool AreBitsCleared(this byte b, byte value) => (~b & value) == value;
    }

How to use:

      [TestMethod()]
      public void TestBits()
      {
         // Data
         byte b1 = 0b10010001;
         byte b2 = 0b11010001;
         byte b3 = 0b11010011;
         byte b4 = 0b00010001;

         // In a set mask, 1 means test for 1 in data byte
         byte setMask = 0b10010001;
         Debug.Assert(b1.AreBitsSet(setMask));
         Debug.Assert(b2.AreBitsSet(setMask));
         Debug.Assert(b3.AreBitsSet(setMask));
         Debug.Assert(!b4.AreBitsSet(setMask));

         // In a cleared mask, a 1 means test for 0 in data byte
         byte clearedMask = 0b01101100;
         Debug.Assert(b1.AreBitsCleared(clearedMask));
         Debug.Assert(!b2.AreBitsCleared(clearedMask));
         Debug.Assert(!b2.AreBitsCleared(clearedMask));
         Debug.Assert(b4.AreBitsCleared(clearedMask));
      }
1

Use Enum with [System.Flags] property and byte, it will treat Enum as set of bits. Later use bitwise operator AND, and compare it against needed value. Here we check if 6th bit value is 1.

[Flags]
public enum Days : byte
{
    None      = 0b_0000_0000,  // 0
    Monday    = 0b_0000_0001,  // 1
    Tuesday   = 0b_0000_0010,  // 2
    Wednesday = 0b_0000_0100,  // 4
    Thursday  = 0b_0000_1000,  // 8
    Friday    = 0b_0001_0000,  // 16
    Saturday  = 0b_0010_0000,  // 32
    Sunday    = 0b_0100_0000,  // 64
}
Days meetingDays = Days.Monday | Days.Tuesday  | Days.Wednesday ; 
bool isMeetingOnWednesday = (meetingDays & Days.Wednesday) == Days.Wednesday;
  • You can use `meetingDays.HasFlag(Days.Wednesday)` instead. [Enum.HasFlag Reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.hasflag?view=net-7.0) – 5andr0 Mar 12 '23 at 15:35
0

To check the bits in a 16-bit word:

  Int16 WordVal = 16;
  for (int i = 0; i < 15; i++)
  {
     bitVal = (short) ((WordVal >> i) & 0x1);
     sL = String.Format("Bit #{0:d} = {1:d}", i, bitVal);
     Console.WriteLine(sL);
  }
Jim Lahman
  • 2,691
  • 2
  • 25
  • 21
0
x == (x | Math.Pow(2, y));

int x = 5;

x == (x | Math.Pow(2, 0)) //Bit 0 is ON
x == (x | Math.Pow(2, 1)) //Bit 1 is OFF
x == (x | Math.Pow(2, 2)) //Bit 2 is ON
Community
  • 1
  • 1
  • 4
    It is usually a good practice on SO to explain your solution, more the why than the how. – ForceMagic Oct 11 '12 at 03:41
  • 1
    OMG, let's set aside question whether compiler would precalc all those Math.Pow for you, but why not do the ((x & Math.Pow) != 0) instead? It's clearer and could save some nanoseconds too. – Konstantin Apr 30 '17 at 01:43
  • 4
    Don't do that! `Math.Pow()` returns a double. You should avoid that when you work with bits / flags. If you use any kind of floats instead of ints you may be facing rounding errors and quantization effects. Instead use left-shifting of 1 by n bits (`1 << n`) as shown in other answers. This is mathematically identical to creating powers of 2 (`2^n == 1< – Jpsy Oct 23 '18 at 08:56
  • totally wrong, bitwise & checks a bit – Mightywill May 30 '22 at 09:42
0

C#6 single-line:

bool IsBitSet(byte b, int pos) => (b >> pos & 1) == 1;
Arvis
  • 8,273
  • 5
  • 33
  • 46