Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Language: Changing the First Four Bits in a Byte

In order to utilize a byte to its fullest potential, I'm attempting to store two unique values into a byte: one in the first four bits and another in the second four bits. However, I've found that, while this practice allows for optimized memory allocation, it makes changing the individual values stored in the byte difficult.

In my code, I want to change the first set of four bits in a byte while maintaining the value of the second four bits in the same byte. While bitwise operations allow me to easily retrieve and manipulate the first four bit values, I'm finding it difficult to concatenate this new value with the second set of four bits in a byte. The question is, how can I erase the first four bits from a byte (or, more accurately, set them all the zero) and add the new set of 4 bits to replace the four bits that were just erased, thus preserving the last 4 bits in a byte while changing the first four?

Here's an example:

//  Changes the first four bits in a byte to the parameter value
public void changeFirstFourBits(byte newFirstFour)
{
    //  If 'newFirstFour' is 0101 in binary, make 'value' 01011111 in binary, changing
    //  the first four bits but leaving the second four alone.
}

private byte value = 255; // binary: 11111111
like image 592
churay Avatar asked Jul 16 '11 19:07

churay


4 Answers

Use bitwise AND (&) to clear out the old bits, shift the new bits to the correct position and bitwise OR (|) them together:

value = (value & 0xF) | (newFirstFour << 4);

Here's what happens:

                       value        : abcdefgh
                       newFirstFour : 0000xyzw

                               0xF  : 00001111
                       value & 0xF  : 0000efgh
                  newFirstFour << 4 : xyzw0000
(value & 0xF) | (newFirstFour << 4) : xyzwefgh
like image 190
hammar Avatar answered Sep 22 '22 08:09

hammar


When I have to do bit-twiddling like this, I make a readonly struct to do it for me. A four-bit integer is called nybble, of course:

struct TwoNybbles
{
    private readonly byte b;
    public byte High { get { return (byte)(b >> 4); } }
    public byte Low { get { return (byte)(b & 0x0F); } {
    public TwoNybbles(byte high, byte low)
    {
        this.b = (byte)((high << 4) | (low & 0x0F));
    }

And then add implicit conversions between TwoNybbles and byte. Now you can just treat any byte as having a High and Low byte without putting all that ugly bit twiddling in your mainline code.

like image 24
Eric Lippert Avatar answered Sep 19 '22 08:09

Eric Lippert


You first mask out you the high four bytes using value & 0xF. Then you shift the new bits to the high four bits using newFirstFour << 4 and finally you combine them together using binary or.

public void changeHighFourBits(byte newHighFour)
{
    value=(byte)( (value & 0x0F) | (newFirstFour << 4));
}

public void changeLowFourBits(byte newLowFour)
{
    value=(byte)( (value & 0xF0) | newLowFour);
}
like image 28
CodesInChaos Avatar answered Sep 20 '22 08:09

CodesInChaos


I'm not really sure what your method there is supposed to do, but here are some methods for you:

void setHigh(ref byte b, byte val) {
    b = (b & 0xf) | (val << 4);
}

byte high(byte b) {
    return (b & 0xf0) >> 4;
}

void setLow(ref byte b, byte val) {
    b = (b & 0xf0) | val;
}

byte low(byte b) {
    return b & 0xf;
}

Should be self-explanatory.

like image 40
Ry- Avatar answered Sep 21 '22 08:09

Ry-