How to read first 4 and last 4 bits from byte?

31,860

Solution 1

Use bitwise AND and shifts, like this:

byte b = 0xAB;
var low = b & 0x0F;
var high = b >> 4;

Solution 2

I would prefer simply using this -

byte a = 68;
byte high_bits = a>>4;
byte low_bits = a&15;

Solution 3

In a convenient struct:

Usage

var hb = new HalvedByte(5, 10);
hb.Low -= 3;
hb.High += 3;
Console.Write(string.Format("{0} / {1}", hb.Low, hb.High));
// 2, 13

Code

public struct HalvedByte
{
    public byte Full { get; set; }

    public byte Low
    {
        get { return (byte)(Full & 0x0F); }

        set
        {
            if (value >= 16)
            {
                throw new ArithmeticException("Value must be between 0 and 16."); 
            }

            Full = (byte)((High << 4) | (value & 0x0F));
        }
    }

    public byte High
    {
        get { return (byte)(Full >> 4); }

        set
        {
            if (value >= 16)
            {
                throw new ArithmeticException("Value must be between 0 and 16.");
            }

            Full = (byte)((value << 4) | Low);
        }
    }

    public HalvedByte(byte full)
    {
        Full = full;
    }

    public HalvedByte(byte low, byte high)
    {
        if (low >= 16 || high >= 16)
        {
            throw new ArithmeticException("Values must be between 0 and 16.");
        }

        Full = (byte)((high << 4) | low);
    }
}

Bonus: Array (Untested)

If you ever need to use an array of these half bytes, this will simplify accessing:

public class HalvedByteArray
{
    public int Capacity { get; private set; }
    public HalvedByte[] Array { get; private set; }

    public byte this[int index]
    {
        get
        {
            if (index < 0 || index >= Capacity)
            {
                throw new IndexOutOfRangeException();
            }

            var hb = Array[index / 2];

            return (index % 2 == 0) ? hb.Low : hb.High;
        }
        set
        {
            if (index < 0 || index >= Capacity)
            {
                throw new IndexOutOfRangeException();
            }

            var hb = Array[index / 2];

            if (index % 2 == 0)
            {
                hb.Low = value;
            }
            else
            {
                hb.High = value;
            }
        }
    }

    public HalvedByteArray(int capacity)
    {
        if (capacity < 0)
        {
            throw new ArgumentException("Capacity must be positive.", "capacity");
        }

        Capacity = capacity;
        Array = new HalvedByte[capacity / 2];
    }
}
Share:
31,860
Alexander
Author by

Alexander

Updated on July 16, 2022

Comments

  • Alexander
    Alexander almost 2 years

    C# how to read first 4 and last 4 bits from byte ?

  • Martin James
    Martin James about 11 years
    Is it necessary to AND off the higher 4 bits after the shift down?
  • Sergey Kalinichenko
    Sergey Kalinichenko about 11 years
    @MartinJames You are correct, ANDing off the rest is not necessary, because C# does not sigh-extends bytes. Thanks!
  • user160357
    user160357 over 3 years
    This code was written in C, but with minor tweaks it will work for C#
  • Ocean Airdrop
    Ocean Airdrop over 2 years
    Very nice and exactly what I was looking for.