C# 中的 CRC32 失败
CRC32 in C# fails
我试图在 C# 中实现我自己的 CRC32 函数。我在这里看到了一个优雅的 JS 解决方案 JavaScript CRC32
所以我想到了这个:
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;
}
}
问题是我的解决方案没有return相同的结果。 Console.WriteLine(Crc32.CalculateCrc32("l"));
结果为 1762050814 而 JS 函数产生 2517025534。JS 结果也是正确的。我做错了什么?
这里的问题是您使用了错误的数据类型。我不熟悉 CRC32 算法,所以我用谷歌搜索找到 http://sanity-free.org/12/crc32_implementation_in_csharp.html 作为参考实现。
我注意到的第一件事是他们使用 uint
而不是 long
。这是有道理的,因为我假设 CRC32 中的 32 意味着它将 return 一个 32 位数字。 long
是一个 64 位有符号整数。
如果您将所有 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
。
我试图在 C# 中实现我自己的 CRC32 函数。我在这里看到了一个优雅的 JS 解决方案 JavaScript CRC32 所以我想到了这个:
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;
}
}
问题是我的解决方案没有return相同的结果。 Console.WriteLine(Crc32.CalculateCrc32("l"));
结果为 1762050814 而 JS 函数产生 2517025534。JS 结果也是正确的。我做错了什么?
这里的问题是您使用了错误的数据类型。我不熟悉 CRC32 算法,所以我用谷歌搜索找到 http://sanity-free.org/12/crc32_implementation_in_csharp.html 作为参考实现。
我注意到的第一件事是他们使用 uint
而不是 long
。这是有道理的,因为我假设 CRC32 中的 32 意味着它将 return 一个 32 位数字。 long
是一个 64 位有符号整数。
如果您将所有 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
。