Вычислить контрольную сумму дополнения двух шестнадцатеричной строки

У меня есть строка0AAE0000463130004144430000" и мне нужно рассчитать дваs дополняет контрольную сумму шестнадцатеричных байтов, составляющих строку.

Формула для примера строки выше

Суммируйте значения: 0A + AE + 00 + 00 + 46 + 31 + 30 + 00 + 41 + 44 + 43 + 00 + 00 = 27 (откажитесь от переполнения)Вычтите результат из 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 и выполнение этого для каждого отдельного символа.

 Oded17 окт. 2012 г., 22:36
Что ж, вы просматриваете каждый символ в строке - вы сначала не конвертируете каждую пару в ее байтовое представление.
 Crake17 окт. 2012 г., 22:38
Если я переключаюсь на byte [] outputBytes = GetBytes (output.TrimStart (':')); Я все еще получаю то же самое (неправильное) значение.

Ответы на вопрос(3)

Попробуйте это вместо этого. Захватите два символа за раз, используя 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;
Решение Вопроса

Ты можешь использоватьSoapHexBinary класс в System.Runtime.Remoting.Metadata.W3cXsd2001.

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"); // 
 Crake17 окт. 2012 г., 22:49
Кроме того, это сработало отлично, спасибо!
 Crake17 окт. 2012 г., 22:47
Почему неt Я сразу заглядываю в пространство имен надежного System.Runtime.Remoting.Metadata.W3cXsd2001? :)
 L.B17 окт. 2012 г., 23:47
@ Камил попробуй это с0x123456781234567812345678  который является достаточно большим, чтобы не соответствовать int (или long)
 Kamil17 окт. 2012 г., 23:57
@ L.B. Правильно, я подумал, что это тривиальный вопрос и проблема в шестнадцатеричном формате в строке. Сожалею.
 Kamil17 окт. 2012 г., 23:40
Вы можете использовать Convert.ToInt32 (), просто добавьте0x» в ваши шестнадцатеричные строки, и Convert распознает данные как шестнадцатеричное число без проблем.

Принятый ответ работает, если вы хотите включить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"));
    }
}

Ваш ответ на вопрос