计算十六进制字符串的二进制补码校验和

时间:2012-10-17 20:33:02

标签: c# twos-complement

我有一个字符串“0AAE0000463130004144430000”,我需要计算组成字符串的十六进制字节的二进制补码校验和。

上面示例字符串的公式是

  1. 总和值:0A + AE + 00 + 00 + 46 + 31 + 30 + 00 + 41 + 44 + 43 + 00 + 00 = 27(丢弃溢出)
  2. 从0x100 = 0xD9
  3. 中减去结果

    D9是此示例的正确校验和,但我无法从C#中的字符串中解析出两位十六进制值。我目前的代码如下:

    string output = "0AAE0000463130004144430000";
    long checksum = 0;
    char[] outputBytes = output.TrimStart(':').ToCharArray();
    
    foreach (var outputByte in outputBytes)
    {
        checksum += Convert.ToInt32(outputByte);
        checksum = checksum & 0xFF;
    }
    
    checksum = 256 - checksum;
    

    然而,这是我可以告诉的ASCII值的总和,并为每个单独的角色做。

3 个答案:

答案 0 :(得分:10)

您可以在System.Runtime.Remoting.Metadata.W3cXsd2001中使用SoapHexBinary类。

soapHexBinary.Value属性将返回一个字节数组

string hexString = "0AAE0000463130004144430000";
byte[] buf = SoapHexBinary.Parse(hexString).Value;

int chkSum = buf.Aggregate(0, (s, b) => s += b) & 0xff;
chkSum = (0x100 - chkSum) & 0xff;

var str = chkSum.ToString("X2"); // <-- D9

答案 1 :(得分:2)

试试这个。使用SubString一次抓取两个字符,并使用带有NumberStyles.AllowHexSpecifier的int.Parse将这对字符作为十六进制值读取。

string output = "0AAE0000463130004144430000";
int checksum = 0;

// You'll need to add error checking that the string only contains [0-9A-F], 
// is an even number of characters, etc.
for(int i = 0; i < output.length; i+=2)
{
   int value = int.Parse(output.SubString(i, 2), NumberStyles.AllowHexSpecifier);
   checksum = (checksum + value) & 0xFF;
}

checksum = 256 - checksum;

答案 2 :(得分:0)

如果要包含System.Runtime.Remoting.Metadata.W3cXsd2001名称空间,则可接受的答案有效。

如果不想包含名称空间,则以下代码将返回正确的结果。此示例与上面的示例之间的区别是添加到返回值的附加& 0xFF。否则,计算针对全零的校验和时,结果将不正确。

public static class ExtensionMethods
{
    public static string MicrochipDataString(this string input)
    {
        int TwosComplement(string s)
        {
            if (s.Length % 2 != 0)
                throw new FormatException(nameof(input));

            var checksum = 0;

            for (var i = 0; i < s.Length; i += 2)
            {
                var value = int.Parse(s.Substring(i, 2), NumberStyles.AllowHexSpecifier);

                checksum = (checksum + value) & 0xFF;
            }

            return 256 - checksum & 0xFF;
        }

        return string.Concat(":", input, TwosComplement(input).ToString("X2"));
    }
}