2015-06-26 2 views
1

Я пытался реализовать свою собственную функцию CRC32 в C#. Я видел элегантное решение в JS здесь JavaScript CRC32 Так что я пришел с этим:CRC32 in C# failed

internal static class Crc32 
    { 
     internal static long CalculateCrc32(string str) 
     { 
      long[] crcTable = Crc32.MakeCrcTable(); 
      long crc = 0^(-1); 

      for (int i = 0; i < str.Length; i++) 
      { 
       char c = str[i]; 
       crc = (crc >> 8)^crcTable[(crc^c) & 0xFF]; 
      } 

      return ~crc; //(crc^(-1)) >> 0; 
     } 

     internal static long[] MakeCrcTable() 
     { 
      long c; 
      long[] crcTable = new long[256]; 
      for (int n = 0; n < 256; n++) 
      { 
       c = n; 
       for (int k = 0; k < 8; k++) 
       { 
        var res = c & 1; 
        c = (res == 1) ? (0xEDB88320^(c >> 1)) : (c >> 1); 
       } 
       crcTable[n] = c; 
      } 

      return crcTable; 
     } 
    } 

Проблема заключается в том, что мое решение не возвращает тот же результат. Console.WriteLine(Crc32.CalculateCrc32("l")); приводит к 1762050814, а функция JS - 2517025534. Результат JS также является правильным. Что я делаю не так?

+0

Вы уверены, что вы связали подходящий вопрос? Тот, с которым вы связаны, связан с кодом символа, а не с JS CRC ... –

+0

Можете ли вы отладить это, чтобы найти проблему? Сбросьте таблицу CRC и проверьте, соответствует ли она. Сбросьте CRC после каждого расчета и посмотрите, когда они расходятся, и т. Д. У нас даже нет вашей ссылочной реализации для сравнения с ... Также google показывает много реализаций C#, которые вы, вероятно, могли бы сравнить с вашими, чтобы найти проблему. – Chris

+1

Одна вещь, которая сразу заставляет меня задаться вопросом, правильно ли вы используете Int64 для вычисления CRC32? Имя предполагает 32 бит, как и реализация здесь: http://sanity-free.org/12/crc32_implementation_in_csharp.html – Chris

ответ

2

Проблема в том, что вы используете неправильный тип данных. Я не знаком с алгоритмом CRC32, поэтому я искал googled, чтобы найти http://sanity-free.org/12/crc32_implementation_in_csharp.html в качестве эталонной реализации.

Первое, что я заметил, это то, что они используют uint вместо long. Это имеет смысл, поскольку я предполагаю, что 32 в CRC32 означает, что он вернет 32-битное число. long - это 64-битный подписанный int.

Если вы меняете все long на uint, мы почти получаем рабочую программу. Единственная строка, которая не будет работать, - c=n, потому что она не может неявно преобразовать int (n) в uint (c). Однако, поскольку мы знаем, что n всегда будет положительным целым, мы можем просто изменить n на тип uint.

Это оставляет меня:

internal static uint CalculateCrc32(string str) 
{ 
    uint[] crcTable = Crc32.MakeCrcTable(); 
    uint crc = 0xffffffff; 
    for (int i = 0; i < str.Length; i++) 
    { 
     char c = str[i]; 
     crc = (crc >> 8)^crcTable[(crc^c) & 0xFF]; 
    } 

    return ~crc; //(crc^(-1)) >> 0; 
} 

internal static uint[] MakeCrcTable() 
{ 
    uint c; 
    uint[] crcTable = new uint[256]; 
    for (uint n = 0; n < 256; n++) 
    { 
     c = n; 
     for (int k = 0; k < 8; k++) 
     { 
      var res = c & 1; 
      c = (res == 1) ? (0xEDB88320^(c >> 1)) : (c >> 1); 
     } 
     crcTable[n] = c; 
    } 

    return crcTable; 
} 

С помощью этого кода Console.WriteLine(Crc32.CalculateCrc32("l"));2517025534 отображает, как и ожидалось.

+0

У меня слишком занятая отладка, чтобы думать о типах. Благодарю. – Cyan

+0

Нет проблем. Мне очень нравятся проблемы отладки, когда они хороши и самодостаточны. :) – Chris