简体   繁体   English

C#中的CRC32失败

[英]CRC32 in C# fails

I was trying to implement my own CRC32 function in C#. 我试图在C#中实现自己的CRC32函数。 I saw an elegant solution in JS here JavaScript CRC32 So I came up with this: 我在这里的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;
        }
    }

The problem is that my solution does not return the same result. 问题是我的解决方案没有返回相同的结果。 Console.WriteLine(Crc32.CalculateCrc32("l")); results in 1762050814 while the JS function produces 2517025534. The JS result is also the correct one. 结果为1762050814,而JS函数产生2517025534。JS结果也是正确的结果。 What am I doing wrong? 我究竟做错了什么?

The problem here is that you are using the wrong datatype. 这里的问题是您使用了错误的数据类型。 I'm not familiar with the CRC32 algorithm so I googled to find http://sanity-free.org/12/crc32_implementation_in_csharp.html as a reference implementation. 我对CRC32算法不熟悉,因此我在Google上找到了http://sanity-free.org/12/crc32_implementation_in_csharp.html作为参考实现。

the first thing I noticed is that they are using uint instead of long . 我注意到的第一件事是他们使用uint而不是long This makes sense as I'd assume the 32 in CRC32 means that it would return a 32 bit number. 这很有意义,因为我假设CRC32中的32表示它将返回32位数字。 long is a 64 bit signed int. long是一个64位带符号的int。

If you change all the long for uint then we nearly get a working program. 如果你改变所有的longuint那么我们几乎得到了工作程序。 The only line that won't work is c=n because it can't implicitly convert an int (n) to a uint (c). 唯一行不通的是c=n因为它无法隐式将int(n)转换为uint(c)。 However since we know n is always going to be a positive integer we can just change n to be of type uint as well. 但是,由于我们知道n始终将是一个正整数,因此我们也可以将n更改为uint类型。

This leaves me with: 这给我留下了:

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;
}

With this code Console.WriteLine(Crc32.CalculateCrc32("l")); 使用此代码, Console.WriteLine(Crc32.CalculateCrc32("l")); displays 2517025534 as expected. 按预期显示2517025534

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM