java实现 循环冗余校验(CRC)算法

算法的要求是如下:

① 装一个16 位寄存器,所有数位均为1。
② 取被校验串的一个字节与16 位寄存器的高位字节进行“异或”运算。运算结果放
入这个16 位寄存器。
③ 把这个16 寄存器向右移一位。
④ 若向右(标记位)移出的数位是1,则生成多项式1010 0000 0000 0001 和这个寄
存器进行“异或”运算;若向右移出的数位是0,则返回③。
⑤ 重复③和④,直至移出8 位。
⑥ 取被校验串的下一个字节
⑦ 重复③~⑥,直至被校验串的所有字节均与16 位寄存器进行“异或”运算,并移位
8 次。
⑧ 这个16 位寄存器的内容即2 字节CRC 错误校验码。
校验码按照先高字节后低字节的顺序存放。

我自己理解实现了下:

 public static short crc16(byte[] data) {
        short crc = (short) 0xFFFF;
        short dxs = (short) 0xA001;
        byte tc;
        byte sbit;
        for (int i = 0; i < data.length; i++) {
            tc = (byte) ((crc & 0xff00) >> 8);
            crc = (short) (tc ^ data[i]);
            for (int r = 0; r < 8; r++) {
                sbit = (byte) (crc & 0x01);
                crc = (short) (crc >> 1);
                if (sbit != 0)
                    crc = (short) (crc ^ dxs);
            }
        }

        System.out.println(bytesToHexString(new byte[] {
                (byte) ((crc & 0xff00) >> 8), (byte) (crc & 0xff) }));

        return crc;
    }

    //将字节数组按16进制输出
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);

            if (stringBuilder.length() != 0) {
                stringBuilder.append(",");
            }
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

可是我计算出的接口和文档上对不上,不知道哪里有问题?

改成这样就行了,因为java里面没有无符号整数,可以用长一点的整数来避免变成负数的问题。

public static short calcCrc16(byte[] data) {

int crc = 0xffff;
int dxs = 0xa001;
int hibyte;
int sbit;
for (int i = 0; i < data.length; i++) {
hibyte = crc >> 8;
crc = hibyte ^ data[i];

        for(int j=0; j<8; j++) {
            sbit = crc & 0x0001;
            crc = crc >> 1;
            if(sbit == 1)
                crc ^= dxs;
        }
    }
    return (short)(crc & 0xffff);
}