PanBocian
PanBocian

Reputation: 63

How to get a bit range from a hexadecimal string and convert it to an integer?

Im asking this question, because couldn't find a solution for this particular case.

I need to extract value (as int or byte) from a hex string and from a given range of bits. For example:

hexString = "0x34840A00"

bits (from calc): 00110100 10000100 00001010 00000000

Now I need bits from 8 to 10: 010

Now convert to int/byte value. Any help? Im struggling with understanding of bit operations here.

Upvotes: 2

Views: 1939

Answers (1)

Frederik Hoeft
Frederik Hoeft

Reputation: 1440

You could first use Convert.FromHexString(hexString) to get the bytes from your hex string. Then you could either use unsafe pointers or BitConverter.ToInt32() to convert said bytes to a 32 bit integer to which you can then apply bit shifts and other bit wise operations to extract the bits you need. For example:

string hexString = "0x34840A00";
byte[] bytes = Convert.FromHexString(hexString);
int myInt = BitConverter.ToInt32(bytes, 0);
// myInt looks like this 00110100 10000100 00001010 00000000
// now shift by 8 bits to the right
myInt >>= 8;
// now it looks like this 00000000 00110100 10000100 00001010
// to get the value of the last 3 bits we need to set the first 29 bits to 0
// so we AND them together with 29 0's followed by 3 1's:
myInt &= 0x00000007;
// which results in the following bits:
// 00000000 00000000 00000000 00000010
// leaving you with an integer of the value 010 in binary or 2 in decimal

The bit shifting and AND-ing always follows the same rules:

  1. If you want the bits starting at index n (as counted from the right-most/least significant bit) then shift right by n bits (in your example n=8 (you don't care about the rightmost 8 bits)).
  2. let m be the number of bits you want to keep starting at position n (in your example you want to keep 3 bits 010). AND the result together with the integer 2^m - 1. In your example m=3 this would be 2^3-1 = 8-1 = 7. Therefore we do myInt &= 0x00000007; or in short myInt &= 0x7;.

Edit: for older .NET versions and simplifying

string hexString = "0x34840A00";
int myInt = Convert.ToInt32(hexString, 16);
// myInt looks like this 00110100 10000100 00001010 00000000
// now shift by 8 bits to the right
myInt >>= 8;
// now it looks like this 00000000 00110100 10000100 00001010
// to get the value of the last 3 bits we need to set the first 29 bits to 0
// so we AND them together with 29 0's followed by 3 1's:
myInt &= 0x00000007;
// which results in the following bits:
// 00000000 00000000 00000000 00000010
// leaving you with an integer of the value 010 in binary or 2 in decimal

The reusable (and pretty fast) approach would therefore be a method like this:

private static int GetBitsFromHexString(string hexString, int startIndexFromRight, int bitsToKeep)
{
    int result = Convert.ToInt32(hexString, 16);
    // shift by startIndexFromRight bits to the right
    result >>= startIndexFromRight;
    // AND the bits together with 32 - bitsToKeep 0's followed by bitsToKeep 1's:
    int bitmask = (1 << bitsToKeep) - 1; // is the same as 2^bitsToKeep - 1.
    // apply bitmask
    result &= bitmask;
    return result;
}

Which you would call like this in your example:

int result = GetBitsFromHexString("0x34840A00", 8, 3);
// result is 2 or 010 in binary 

Upvotes: 2

Related Questions