在C#中将可变大小的十六进制字符串转换为带符号的数字(可变大小的字节)

时间:2018-06-29 05:02:32

标签: c#

C#提供了方法Convert.ToUInt16("FFFF", 16) / Convert.ToInt16("FFFF", 16)将十六进制字符串转换为无符号和有符号的16位整数。这些方法适用于16/32位值,但不适用于12位值。

我想将3个字符长的十六进制字符串转换为有符号整数。我该怎么办?我希望有一种可以使用字符数作为参数来确定带符号值的解决方案。

Convert(string hexString, int fromBase, int size)

  • Convert("FFF", 16, 12)返回-1

  • Convert("FFFF", 16, 16)返回-1

  • Convert("FFF", 16, 16)返回4095

2 个答案:

答案 0 :(得分:2)

我想到将12位带符号的十六进制转换为带符号的整数的最简单方法如下:

string value = "FFF";    
int convertedValue = (Convert.ToInt32(value, 16) << 20) >> 20; // -1

该想法是将结果尽可能向左移动,以使负位对齐,然后再次向右移动到原始位置。之所以有效,是因为“有符号右移”操作可将负位保持在原位。

您可以将其概括为以下方法:

int Convert(string value, int fromBase, int bits)
{
    int bitsToShift = 32 - bits;
    return (Convert.ToInt32(value, fromBase) << bitsToShift) >> bitsToShift;
}

如果在使用12位十六进制字符串时需要16位值,则可以将结果强制转换为short。此方法的性能将与16位版本相同,因为short上的移位运算符无论如何都将值强制转换为int,这使您可以更灵活地在需要时指定16个以上的位,而无需编写其他位方法。

答案 1 :(得分:1)

啊,您想为一定数量的位计算Two's Complement(在您的情况下为12,但实际上它应该对任何东西都有效)。

这是C#中的代码,是从Wiki文章中的Python示例中公然偷来的:

int Convert(string hexString, int fromBase, int num_bits)
{
    var i = System.Convert.ToUInt16(hexString, fromBase);
    var mask = 1 << (num_bits - 1);
    return (-(i & mask) + (i & ~mask));
}
  • Convert("FFF", 16, 12)返回-1
  • Convert("4095", 10, 12)也是-1,符合预期