views:

160

answers:

3

Scenario:

I have a string of hexadecimal characters which encode 8-bit signed integers. Each two characters represent a byte which employ the leftmost (MSB) bit as the sign (rather than two's complement). I am converting these to signed ints within a loop and wondered if there's a better way to do it. There are too many conversions and I am sure there's a more efficient method that I am missing.

Current Code:

string strData = "FFC000407F"; // example input data, encodes: -127, -64, 0, 64, 127
int v;
for (int x = 0; x < strData.Length/2; x++)
{
    v = HexToInt(strData.Substring(x * 2, 2));
    Console.WriteLine(v); // do stuff with v
}

private int HexToInt(string _hexData)
{
    string strBinary = Convert.ToString(Convert.ToInt32(_hexData, 16), 2).PadLeft(_hexData.Length * 4, '0');
    int i = Convert.ToInt32(strBinary.Substring(1, 7), 2);
    i = (strBinary.Substring(0, 1) == "0" ? i : -i);
    return i;
}

Question:

Is there a more streamlined and direct approach to reading two hex characters and converting them to an int when they represent a signed int (-127 to 127) using the leftmost bit as the sign?

+3  A: 

Just covert it to an int and handle the sign bit by testing the size of the converted number and masking off the sign bit.

private int HexToInt(string _hexData)
{
    int number = Convert.ToInt32(_hexData, 16);
    if (number >= 0x80)
       return -(number & 0x7F);
    return number;
}
shf301
JYelton
@JYelton, yes I did. Edited answer.
shf301
+1  A: 

Like this: (Tested)

(int)unchecked((sbyte)Convert.ToByte("FF", 16))

Explanation:

The unchecked cast to sbyte will perform a direct cast to a signed byte, interpreting the final bit as a sign bit.

However, it has a different range, so it won't help you.

SLaks
This results in the numbers: -1, -64, 0, 64, 127
JYelton
+1  A: 
sbyte SignAndMagnitudeToTwosComplement(byte b)
{
    var isNegative = ((b & 0x80) >> 7);
    return (sbyte)((b ^ 0x7F * isNegative) + isNegative);
}

Then:

sbyte ReadSignAndMagnitudeByte(string hex)
{
    return SignAndMagnitudeToTwosComplement(Convert.ToByte(hex,16));
}
Porges
This results in the numbers: 0, -63, 0, 64, 127
JYelton
Doh; for some reason I wrote it thinking your numbers were in one's complement, but they're actually sign-magnitude. I've updated my answer :) - that'll teach me not to test against the given data!
Porges
+1 thanks for the update
JYelton