How do I convert hex string into signed integer? - c#

I'm getting a hex string that needs to be converted to a signed 8-bit integer. Currently I'm converting using Int16/Int32, which will obviously not give me a negative value for an 8-bit integer. If I get the value 255 in Hex, how do I convert that to -1 in decimal? I assume I want to use an sbyte, but I'm not sure how to get that value in there properly.

You can use Convert.ToSByte
For example:
string x = "aa";
sbyte v = Convert.ToSByte(x, 16);
// result: v = 0xAA or -86
You can also use sbyte.Parse
For example:
string y = "bb";
sbyte w = sbyte.Parse(y, System.Globalization.NumberStyles.HexNumber);
// result: w = 0xBB or -69
To answer your question about the upper or lower byte of an Int16:
string signed_short = "feff";
// Truncate 16 bit value down to 8 bit
sbyte b1 = (sbyte)Convert.ToInt16(signed_short, 16);
sbyte b2 = (sbyte)short.Parse(signed_short, System.Globalization.NumberStyles.HexNumber);
// result: b1 = 0xFF or -1
// result: b2 = 0xFF or -1
// Use upper 8 bit of 16 bit
sbyte b3 = (sbyte)(Convert.ToInt16(signed_short, 16) >> 8);
sbyte b4 = (sbyte)(short.Parse(signed_short, System.Globalization.NumberStyles.HexNumber) >> 8);
// result: b3 = 0xFE or -2
// result: b4 = 0xFE or -2

You need to perform an unchecked cast, like this:
sbyte negativeOne = unchecked((sbyte)255);

My solution was to put the first take the first 8 bits of the 16 bit integer and store them in an sbyte.

Related

c# how to store two 4 bit numbers into one byte

So I have two 4 bits number (between 0 and 15):
int a = 1;
int b = 15;
And I want to store them into 1 byte.
This is what I have try:
byte[] bytesA = BitConverter.GetBytes(a);
byte[] bytesB = BitConverter.GetBytes(b);
byte a = bytesA[0];
byte b = bytesB[1];
Sins a byte is 8 bits and you have 2 4 bit values, you will need to shift one of the values to occupy the high 4 bits of the resulting byte, like so:
byte ab = (byte)((a << 4) | (b & 0xF));
To get a out of ab:
byte a = (byte)((ab >> 4) & 0xF);
To get b out of ab:
byte b = (byte)(ab & 0xF);

short to byte conversion

I am trying to convert a short type into 2 bytes type for store in a byte array, here is the snippet thats been working well "so far".
if (type == "short")
{
size = data.size;
databuffer[index+1] = (byte)(data.numeric_data >> 8);
databuffer[index] = (byte)(data.numeric_data & 255);
return size;
}
Numeric_data is int type. It all worked well till i process the value 284 (decimal). It turns out that 284 >> 8 is 1 instead of 4.
The main goal is to have:
byte[0] = 28
byte[1] = 4
Is this what you are looking for:
static void Main(string[] args)
{
short data=284;
byte[] bytes=BitConverter.GetBytes(data);
// bytes[0] = 28
// bytes[1] = 1
}
Just for fun:
public static byte[] ToByteArray(short s)
{
//return, if `short` can be cast to `byte` without overflow
if (s <= byte.MaxValue)
return new byte[] { (byte)s };
List<byte> bytes = new List<byte>();
byte b = 0;
//determine delta through the number of digits
short delta = (short)Math.Pow(10, s.ToString().Length - 3);
//as soon as byte can be not more than 3 digits length
for (int i = 0; i < 3; i++)
{
//take first 3 (or 2, or 1) digits from the high-order digit
short temp = (short)(s / delta);
if (temp > byte.MaxValue) //if it's still too big
delta *= 10;
else //the byte is found, break the loop
{
b = (byte)temp;
break;
}
}
//add the found byte
bytes.Add(b);
//recursively search in the rest of the number
bytes.AddRange(ToByteArray((short)(s % delta)));
return bytes.ToArray();
}
this recursive method does what the OP need with at least any positive short value.
Why would 284 >> 8 would be 4?
Why would 284 be split in two bytes equal to 28 and 4?
The binary representation of 284 is 0000 0001 0001 1100. As you can see, there are two bytes (eight bits) which are 0000 0001 (256 in decimal) and 0001 1100 (28 in decimal).
284 >> 8 is 1 (0000 0001) and it is correct.
284 should be split in two bytes equal to 256 and 24.
You conversion is correct!
If you insist:
short val = 284;
byte a = (byte)(val / 10);
byte b = (byte)(val % 10);
Disclaimer:
This does not make much sense, but it is what you want. I assume you want values from 0 to 99. The logical thing to do would be to use 100 as the denominator and not 10. But then again, I have no idea what you want to do.
Drop the nonsense conversion you are using and go for System.BitConverter.ToInt16
//to bytes
var buffer = System.BitConverter.GetBytes(284); //your short value
//from bytes
var value = System.BitConverter.ToInt16(buffer, 0);

C# Convert Int To Two Hex Bytes?

I have an integer that I need to convert to a four digit hex value.
For example, lets say the int value is 16. What I am looking for is a way to go from 16 to
0x00 0x10.
Any suggestions would be greatly appreciated!!!
Try this:
var input = 16;
var bytes = new byte[2];
bytes[0] = (byte)(input >> 8); // 0x00
bytes[1] = (byte)input; // 0x10
var result = (bytes[0] << 8)
| bytes[1];
// result == 16
Here's one with regular expressions, just for fun:
Regex.Replace(number.ToString("X4"), "..", "0x$0 ").TrimEnd();
Alternately, a little more general solution is to do it by byte array (then you can use this for strings or other data types)
public static string ByteArrayToString(byte[] ba)
{
string hex = BitConverter.ToString(ba);
return hex.Replace("-","");
}
int i = 39;
string str = "ssifm";
long l = 93823;
string hexi = ByteArrayToString(BitConverter.GetBytes(i));
string hexstr = ByteArrayToString(Encoding.Ascii.GetBytes(str));
string hexl = ByteArrayToString(BitConverter.GetBytes(l));
This returns them in a 'FF' format, you can add the '0x' yourself by adding this after the ToString() instead:
return "0x"+hex.Replace("-", " 0x");
Shift it! Mask it! Mask it! string.Format it!
int n = 16;
string.Format("0x{0:x2} 0x{1:x2}", (n & 0xff00) >> 8, n & 0xff); // 0x00 0x10
Here's a demo.
The x2 format specifier means a 2-digit hexadecimal value.
Okay, apparently you just want two bytes. Hexadecimal is not relevant here.
byte lowByte = (byte)(n & 0xff);
byte highByte = (byte)(n >> 8 & 0xff);

Converting 3 bytes into signed integer in C#

I'm trying to convert 3 bytes to signed integer (Big-endian) in C#.
I've tried to use BitConverter.ToInt32 method, but my problem is what value should have the lats byte.
Can anybody suggest me how can I do it in different way?
I also need to convert 5 (or 6 or 7) bytes to signed long, is there any general rule how to do it?
Thanks in advance for any help.
As a last resort you could always shift+add yourself:
byte b1, b2, b3;
int r = b1 << 16 | b2 << 8 | b3;
Just swap b1/b2/b3 until you have the desired result.
On second thought, this will never produce negative values.
What result do you want when the msb >= 0x80 ?
Part 2, brute force sign extension:
private static int Bytes2Int(byte b1, byte b2, byte b3)
{
int r = 0;
byte b0 = 0xff;
if ((b1 & 0x80) != 0) r |= b0 << 24;
r |= b1 << 16;
r |= b2 << 8;
r |= b3;
return r;
}
I've tested this with:
byte[] bytes = BitConverter.GetBytes(p);
int r = Bytes2Int(bytes[2], bytes[1], bytes[0]);
Console.WriteLine("{0} == {1}", p, r);
for several p.
The last value should be 0 if it isn't set for a positive number, 256 for a negative.
To know what you should pass in, you can try converting it the other way:
var bytes = BitConverter.GetBytes(i);
int x = BitConverter.ToInt32(bytes, 0);
To add to the existing answers here, there's a bit of a gotcha in that Bitconverter.ToInt32() will throw an ArgumentException if the array is less than sizseof(int) (4) bytes in size;
Destination array is not long enough to copy all the items in the collection. Check array index and length.
Given an array less than sizeof(int) (4) bytes in size, you can compensate for left/right padding like so;
Right-pad
Results in positive Int32 numbers
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, 0, sourceBytes.Length);
sourceBytes = padded;
Left-pad
Results in negative Int32 numbers, assuming non-zero value at byte index sourceBytes.Length - 1.
int intByteSize = sizeof(int);
byte[] padded = new byte[intByteSize];
Array.Copy(sourceBytes, 0, padded, intByteSize - sourceBytes.Length, sourceBytes.Length);
sourceBytes = padded;
Once padded, you can safely call int myValue = BitConverter.ToInt32(sourceBytes, 0);.

Perform signed arithmetic on numbers defined as bit ranges of unsigned bytes

I have two bytes. I need to turn them into two integers where the first 12 bits make one int and the last 4 make the other. I figure i can && the 2nd byte with 0x0f to get the 4 bits, but I'm not sure how to make that into a byte with the correct sign.
update:
just to clarify I have 2 bytes
byte1 = 0xab
byte2 = 0xcd
and I need to do something like this with it
var value = 0xabc * 10 ^ 0xd;
sorry for the confusion.
thanks for all of the help.
int a = 10;
int a1 = a&0x000F;
int a2 = a&0xFFF0;
try to use this code
For kicks:
public static partial class Levitate
{
public static Tuple<int, int> UnPack(this int value)
{
uint sign = (uint)value & 0x80000000;
int small = ((int)sign >> 28) | (value & 0x0F);
int big = value & 0xFFF0;
return new Tuple<int, int>(small, big);
}
}
int a = 10;
a.UnPack();
Ok, let's try this again knowing what we're shooting for. I tried the following out in VS2008 and it seems to work fine, that is, both outOne and outTwo = -1 at the end. Is that what you're looking for?
byte b1 = 0xff;
byte b2 = 0xff;
ushort total = (ushort)((b1 << 8) + b2);
short outOne = (short)((short)(total & 0xFFF0) >> 4);
sbyte outTwo = (sbyte)((sbyte)((total & 0xF) << 4) >> 4);
Assuming you have the following to bytes:
byte a = 0xab;
byte b = 0xcd;
and consider 0xab the first 8 bits and 0xcd the second 8 bits, or 0xabc the first 12 bits and 0xd the last four bits. Then you can get the these bits as follows;
int x = (a << 4) | (b >> 4); // x == 0x0abc
int y = b & 0x0f; // y == 0x000d
edited to take into account clarification of "signing" rules:
public void unpack( byte[] octets , out int hiNibbles , out int loNibble )
{
if ( octets == null ) throw new ArgumentNullException("octets");
if ( octets.Length != 2 ) throw new ArgumentException("octets") ;
int value = (int) BitConverter.ToInt16( octets , 0 ) ;
// since the value is signed, right shifts sign-extend
hiNibbles = value >> 4 ;
loNibble = ( value << 28 ) >> 28 ;
return ;
}

Categories

Resources