【问题标题】:Calculate two's complement checksum of hexadecimal string计算十六进制字符串的补码校验和
【发布时间】:2012-10-17 20:33:01
【问题描述】:

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

上面示例字符串的公式是

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

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 值求和,并对每个单独的字符进行求和。

【问题讨论】:

  • 好吧,你正在遍历字符串中的每个字符——你不是先将每一对转换为它的字节表示。
  • 如果我切换到 byte[] outputBytes = GetBytes(output.TrimStart(':'));我仍然得到相同的(不正确的)值。

标签: c# twos-complement


【解决方案1】:

您可以在 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

【讨论】:

  • 我为什么不立即查看可信赖的 System.Runtime.Remoting.Metadata.W3cXsd2001 命名空间? :)
  • 您可以使用 Convert.ToInt32(),只需在您的十六进制字符串中添加“0x”,Convert 就会毫无问题地将数据识别为十六进制数。
  • @Kamil 用 0x123456781234567812345678 试试,它大到不适合 int(或 long)
  • @L.B 对,我认为这是微不足道的问题,问题是字符串中的十六进制格式。对不起。
【解决方案2】:

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

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;

【讨论】:

    【解决方案3】:

    如果您想包含 System.Runtime.Remoting.Metadata.W3cXsd2001 命名空间,则接受的答案有效。

    如果您不想包含命名空间,以下代码将返回正确的结果。这个例子和上面例子的区别是在返回值上增加了额外的&amp; 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"));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-24
      • 1970-01-01
      • 2012-08-27
      • 2019-03-01
      • 1970-01-01
      • 2020-09-09
      • 2013-06-12
      • 1970-01-01
      相关资源
      最近更新 更多