将负数解码为十六进制字符串中的浮点值

本文关键字:字符串 十六进制 解码 | 更新日期: 2023-09-27 17:59:39

我有一个十六进制字符串,它是数值,来自外部设备的串行。我正在使用一次解码一个块

string tmpValue(incoming hex data, such as FE7258);
int valueInt = Convert.ToInt32(tmpValue, 16);
float XCoord = ((float)valueInt / 100);

我能够根据设备输出检查XCoord的输出,当数字为正数时,这可以正常工作。然而,当它们为负数时,我的结果就会跳到错误的地方。

即使使用这个在线转换器:

十六进制到十进制转换器

我看到,当一个负数被转换,然后又被转换回来时,它就不再是同一个数字了。

有办法绕过这个吗?如何处理十六进制到浮点转换中的负值?

将负数解码为十六进制字符串中的浮点值

当使用负数时,我们实际上使用的是补码ones:

https://en.wikipedia.org/wiki/Two%27s_complement

也就是说,我们使用而不是负-x

-x == ~x + 1

例如,对于-123,我们有

  123     = 0000 0000 0111 1011 (binary)
 ~123     = 1111 1111 1000 0100
 ~123 + 1 = 1111 1111 1000 0101 (binary) == FF85 (Hex)

当您将FF85转换回时,您有两个选项:

  • FF85视为2字节有符号值(您将取回-123
  • FF85视为4字节有符号值或2字节无符号(您将得到65413

在您的情况下(奇怪的3字节整数值)

private static String ToHex(int value) {
  return (value & 0xFFFFFF).ToString("X6");
}
private static int FromHex(String value) {
  int v = Convert.ToInt32(value, 16);
  unchecked {
    return (v <= 0x7FFFFF) ? v : v | (int)0xFF000000;
  }
}

测试:

int x = -123;
// FFFF85
string hex = ToHex(x);
// Back -123
int back = FromHex(hex); 
// -101800
Console.Write(FromHex("FE7258"));

如果您使用非标准的字节大小,例如三个字节作为问题帖子,您可以通过简单的减法执行转换:

public static int ThreeByteHexToSignedInt(string hex)
{
    var val = Int32.Parse(hex, System.Globalization.NumberStyles.AllowHexSpecifier);
    if(val > 0xEFFFFF) // If greater than maximum postive 3 byte int
    {
        val = val - 0xFFFFFF - 1; // take the compliment
    }
    return val;
}

例如:

ThreeByteHexToSignedInt("000001"); // Returns 1
ThreeByteHexToSignedInt("FFFFFF"); // Returns -1
ThreeByteHexToSignedInt("FE7258"); // Returns -101800
ThreeByteHexToSignedInt("00FFFE"); // Returns 65534

对于float/double,您可以只获取此操作的结果并执行直接强制转换,或者使用Convert静态类。