Checking if a bit is set or not
Asked Answered
N

12

76

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

bool IsBitSet(Byte b,byte nPos)
{
   return .....;
}
Nawrocki answered 12/3, 2010 at 9:45 Comment(2)
It sounds like a homework problem but think how much people get benifit from this code snipset..Nawrocki
I'm using this at my job. The struggle is real.Habit
P
206

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.

Prendergast answered 12/3, 2010 at 9:50 Comment(2)
yet another one-liner I always google for instead of just learn it :)Chopfallen
I mean, this is also useful for cpp and cLegalize
R
12

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

bool IsBitSet(byte b, int pos)
{
   return ((b >> pos) & 1) != 0;
}
Resuscitate answered 17/2, 2018 at 18:35 Comment(0)
T
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. :)

Tarsal answered 12/3, 2010 at 9:49 Comment(5)
Ok. Byte of 3, test if bit 1 is set. So 1<<1 is 2. 2&3 isn't true. Fail.Counterspy
@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.Tantalite
Perhaps the check should be for non-zero? afaik, non-zero ain't true.Counterspy
Yes the check should be for non-zero instead of true. My C++ background :)Tarsal
+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.Rudbeckia
T
11

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.

These answered 14/5, 2013 at 1:55 Comment(2)
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.Brunt
@Brunt If performance is your be-all-end-all, why are you using bytes over ints in the first place?Rather
H
5

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

Hak answered 12/3, 2010 at 9:50 Comment(1)
I prefer this way around too, left shifting just seems so unnatural :)Habakkuk
P
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];
}
Peddada answered 14/5, 2011 at 2:35 Comment(2)
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.Pagandom
I'm not gonna downvote you or anything but if you're looking for performance then you shouldn't do this.Newscast
M
2

something like

return ((0x1 << nPos) & b) != 0
Monkhmer answered 12/3, 2010 at 9:50 Comment(0)
L
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));
      }
Loiretcher answered 5/12, 2022 at 18:28 Comment(0)
O
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;
Overwork answered 3/1, 2023 at 19:54 Comment(1)
You can use meetingDays.HasFlag(Days.Wednesday) instead. Enum.HasFlag ReferenceMannerless
R
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);
  }
Redblooded answered 9/5, 2012 at 19:57 Comment(0)
A
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
Adscription answered 28/7, 2012 at 19:57 Comment(4)
It is usually a good practice on SO to explain your solution, more the why than the how.Cringle
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.Apc
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<<n) and does not create any quantization deviations because it is all done on integers.Transcription
totally wrong, bitwise & checks a bitDielectric
H
0

C#6 single-line:

bool IsBitSet(byte b, int pos) => (b >> pos & 1) == 1;
Hellish answered 25/11, 2022 at 20:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.