简体   繁体   English

C#的CRC 4实现

[英]CRC 4 implementation for C#

Solved by this code -> https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1 通过此代码解决 - > https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1


I searched the web for a CRC 4 implementation in C# because I have to calculate a checksum by 我在网上搜索了C#中的CRC 4实现,因为我必须通过计算校验和

Changing the numbers of the barcode into Hex representation, then to bytes and then to bits and then calculate a CRC4 checksum on the bit stream. 将条形码的数量更改为十六进制表示,然后更改为字节,然后更改为位,然后在位流上计算CRC4校验和。

I already found this question from 8 years ago without an answer CRC-4 implementation in C# . 我已经在8年前找到了这个问题而没有在C#中回答CRC-4的实现

I tried changing the CRC 8 and 16 implementations to CRC 4 but they don't quite get the result I require. 我尝试将CRC 8和16实现更改为CRC 4,但它们并没有完全得到我需要的结果。

0130E0928270FFFFFFF should evaluate to 7 . 0130E0928270FFFFFFF应评估为7

I found two C implementation but was unable to convert them to C#. 我找到了两个C实现但无法将它们转换为C#。 For example this one: 例如这一个:

 short[] crc4_tab = {
 0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
 0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};

/**
* crc4 - calculate the 4-bit crc of a value.
* @crc:  starting crc4
* @x:    value to checksum
* @bits: number of bits in @x to checksum
*
* Returns the crc4 value of @x, using polynomial 0b10111.
*
* The @x value is treated as left-aligned, and bits above @bits are ignored
* in the crc calculations.
*/
short crc4(uint8_t c, uint64_t x, int bits)
{
    int i;

    /* mask off anything above the top bit */
    x &= (1ull << bits) -1;

    /* Align to 4-bits */
    bits = (bits + 3) & ~0x3;

    /* Calculate crc4 over four-bit nibbles, starting at the MSbit */
    for (i = bits - 4; i >= 0; i -= 4)
    c = crc4_tab[c ^ ((x >> i) & 0xf)];

    return c;
}

My current generation code (unit test) looks like this: 我当前的代码(单元测试)如下所示:

[TestMethod]
public void x()
{
    var ordnungskennzeichen = 01;
    var kundennummer = 51251496;
    var einlieferungsbel = 9999;
    var sendungsnr = 16777215;

    var hex_ordnungskennzeichen = ordnungskennzeichen.ToString("x2");
    var hex_kundennummer = kundennummer.ToString("x2");
    var hex_einlieferungsbel = einlieferungsbel.ToString("x2");
    var hex_sendungsnr = sendungsnr.ToString("x2");

    var complete = hex_ordnungskennzeichen + hex_kundennummer + hex_einlieferungsbel + hex_sendungsnr;

    var bytes = Encoding.ASCII.GetBytes(complete);

    //var computeChecksum = crc4(???);
    //   Console.WriteLine(computeChecksum);

}

short[] crc4_tab = {
    0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
    0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};

/**
* crc4 - calculate the 4-bit crc of a value.
* @crc:  starting crc4
* @x:    value to checksum
* @bits: number of bits in @x to checksum
*
* Returns the crc4 value of @x, using polynomial 0b10111.
*
* The @x value is treated as left-aligned, and bits above @bits are ignored
* in the crc calculations.
*/

short crc4(byte c, ulong x, int bits)
{
    int i;

    /* mask off anything above the top bit */
    x &= ((ulong)1 << bits) -1;

    /* Align to 4-bits */
    bits = (bits + 3) & ~0x3;

    /* Calculate crc4 over four-bit nibbles, starting at the MSbit */
    for (i = bits - 4; i >= 0; i -= 4)
        c = (byte) crc4_tab[c ^ ((x >> i) & 0xf)];

    return c;
}

Converting it to C# is not very hard. 将它转换为C#并不是很难。 c is initial or previous nibble (4-bit number), x is 64bit number you want to calculate crc4 of, bits is number of bits in that 64bit number to actually use (the rest are ignored). c是初始或前一个半字节(4位数), x是要计算crc4的64位数, bits是实际使用的64位数的位数(其余被忽略)。 Since you have array of bytes - you don't need to use 64bit number as x - use can just use byte. 由于你有字节数组 - 你不需要使用64位数作为x - 使用可以只使用字节。 Then the first two lines are irrelevant for you, because all they do is throwing away irrelevant bits from 64bit number and ensuring bits is divisable by 4. So after removing irrelevant lines your implementation becomes: 然后前两行对你来说是无关紧要的,因为它们所做的就是丢弃64位数字中不相关的位,并确保bits可以被4除。所以在删除不相关的行后,你的实现变为:

static readonly byte[] crc4_tab = {
    0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
    0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};

static byte crc4(byte c, byte x) {
    var low4Bits = x & 0x0F;
    var high4Bits = x >> 4;
    c = crc4_tab[c ^ high4Bits];
    c = crc4_tab[c ^ low4Bits];

    return c;
}

static byte crc4(byte[] array) {
    byte start = 0;
    foreach (var item in array) {
        start = crc4(start, item);
    }
    return start;
}

After further testing and communication with the Deutsche Post AG we made a correct implementation (for the purpose of Deutsche Post at least): 经过与德国邮政AG的进一步测试和沟通,我们做出了正确的实施(至少为德国邮政的目的):

https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1 https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1

For the purpose of Deutsche Post as well, I'd like to contribute a rather less complex algorithm wich may more easily be translated into other languages as well: 为了德国邮政的目的,我想提供一个相当简单的算法,它可以更容易地翻译成其他语言:

       private string crc4(string sText) {
        int iCRC;
        int iPoly;
        int iByte;
        int iBit;
        byte[] bText;
        sText = sText.Replace(" ", "");
        iPoly = 0x13 << 3;
        iCRC = 0;
        bText = Encoding.Default.GetBytes(sText);
        for (iByte=0; iByte < bText.Length; iByte++){
            iCRC = iCRC ^ bText[iByte];
            for (iBit = 0; iBit < 8; iBit++){
                if ((iCRC & 0x80) != 0){
                    iCRC = iCRC ^ iPoly;
                }
                iCRC = iCRC << 1;
            }
        }
        iCRC = iCRC >> 4;

        return String.Format("{0:X}", iCRC);
    }

Fed with ie "A0 0101 002B 00 000C D10" the above code will calculate "F" as the correct check digit. 用“A0 0101 002B 00 000C D10”代替上述代码将“F”计算为正确的校验位。 (and tested with numerous other input values) (并使用许多其他输入值进行测试)

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

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