将CRC8从C翻译成Java

将CRC8从C翻译成Java,java,c,crc,Java,C,Crc,我收到一段C代码,它计算字节数组的CRC8值。 我需要把它翻译成Java 这里是C代码: CRC_POLYNOM = 0x9c; CRC_PRESET = 0xFF; unsigned int CRC = CRC_PRESET; for (i = 0; i < Len; i++) { crc ^= FRAME[i]; for (j = 0; j < 8; j++) { if (crc & 0x01) crc = (crc >>

我收到一段C代码,它计算字节数组的CRC8值。 我需要把它翻译成Java

这里是C代码:

CRC_POLYNOM = 0x9c;
CRC_PRESET = 0xFF;

unsigned int CRC = CRC_PRESET;
for (i = 0; i < Len; i++)
{
  crc ^= FRAME[i];
  for (j = 0; j < 8; j++)
  {
    if (crc & 0x01)
        crc = (crc >> 1) ^ CRC_POLYNOM;
    else
        crc = (crc >> 1);
  }
}
C代码返回29,而我的Java代码返回44。 我做错了什么

我认为这是因为Java的纯签名数据类型,所以我如何修复它

if (crc & 0x01)
此测试是否设置了最低位

if ((crc & 0x01) == 0)
这将测试底部钻头是否清晰

您还应该在Java代码中使用无符号右移(即在两个位置使用
>>
而不是
>
),并在返回结果之前使用
0xff
屏蔽结果

编辑最后您需要更改:

crc ^= b[i];
为此:

crc ^= b[i] & 0xff;
但是,您应该真正抛弃它,并查找表驱动方法。速度是这个的八倍

编辑2表驱动版本,经过修订以实现
java.util.zip.Checksum:

public class CRC8 implements Checksum
{
    private final short init;
    private final short[]   crcTable = new short[256];
    private short   value;

    /**
     * Construct a CRC8 specifying the polynomial and initial value.
     * @param polynomial Polynomial, typically one of the POLYNOMIAL_* constants.
     * @param init Initial value, typically either 0xff or zero.
     */
    public CRC8(int polynomial, short init)
    {
        this.value = this.init = init;
        for (int dividend = 0; dividend < 256; dividend++)
        {
            int remainder = dividend ;//<< 8;
            for (int bit = 0; bit < 8; ++bit)
                if ((remainder & 0x01) != 0)
                    remainder = (remainder >>> 1) ^ polynomial;
                else
                    remainder >>>= 1;
            crcTable[dividend] = (short)remainder;
        }
    }

    @Override
    public void update(byte[] buffer, int offset, int len)
    {
        for (int i = 0; i < len; i++)
        {
            int data = buffer[offset+i] ^ value;
            value = (short)(crcTable[data & 0xff] ^ (value << 8));
        }
    }

    /**
     * Updates the current checksum with the specified array of bytes.
     * Equivalent to calling <code>update(buffer, 0, buffer.length)</code>.
     * @param buffer the byte array to update the checksum with
     */
    public void update(byte[] buffer)
    {
        update(buffer, 0, buffer.length);
    }

    @Override
    public void update(int b)
    {
        update(new byte[]{(byte)b}, 0, 1);
    }

    @Override
    public long getValue()
    {
        return value & 0xff;
    }

    @Override
    public void reset()
    {
        value = init;
    }

    public static void  main(String[] args)
    {
        final int   CRC_POLYNOM = 0x9C;
        final byte  CRC_INITIAL = (byte)0xFF;

        final byte[]    data = {1, 56, -23, 3, 0, 19, 0, 0, 2, 0, 3, 13, 8, -34, 7, 9, 42, 18, 26, -5, 54, 11, -94, -46, -128, 4, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, -32, -80, 0, 98, -5, 71, 0, 64, 0, 0, 0, 0, -116, 1, 104, 2};
        CRC8    crc8 = new CRC8(CRC_POLYNOM, CRC_INITIAL);
        crc8.update(data,0,data.length);
        System.out.println("Test successful:\t"+(crc8.getValue() == 29));
    }
}
您的“^”实际上已经像箭头一样指向错误所在的部分

相当于

if (crc & 0x01)
在Java中是(因为Java需要if中的布尔表达式)


我为您的问题创建了一个完整/独立的C程序:

#include <stdio.h>

#define CRC_POLYNOM 0x9c
#define CRC_PRESET 0xFF

int main() {
    unsigned int crc = CRC_PRESET;
    unsigned char FRAME[] = {1, 56, -23, 3, 0, 19, 0, 0, 2, 0, 3, 13, 8, -34, 7, 9, 42, 18, 26, -5, 54, 11, -94, -46, -128, 4, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, -32, -80, 0, 98, -5, 71, 0, 64, 0, 0, 0, 0, -116, 1, 104, 2};
    for(int i = 0; i < sizeof(FRAME); i++) {
        crc ^= FRAME[i];
        for(int j = 0; j < 8; j++) {
            if(crc & 0x01) {
                crc = (crc >> 1) ^ CRC_POLYNOM;
            } else {
                crc = (crc >> 1);
            }
        }
    }
    printf("%u\n", crc);
    return 0;
}
#包括
#定义CRC_多项式0x9c
#定义CRC_预设0xFF
int main(){
无符号整数crc=crc\U预置;
无符号字符帧[]={1,56,-23,3,0,19,0,0,2,0,3,13,8,-34,7,9,42,18,26,-5,54,11,-94,-46,-128,4,48,52,0,0,0,0,0,0,0,0,0,0,0,0,1,1,-32,-80,0,98,-5,71,0,64,0,0,0,0,0,0,0,0,0,0,-116,1,104,2};
对于(int i=0;i>1)^crc多项式;
}否则{
crc=(crc>>1);
}
}
}
printf(“%u\n”,crc);
返回0;
}
以下是自动创建的等效Java代码:

软件包演示;
公共类翻译{
公共最终静态整数CRC_多项式=0x9c;
公共最终静态整数CRC_预设=0xFF;
公共静态void main(字符串[]args){
int crc_=crc_预设值;
字节[]帧_={1,56,-23,3,0,19,0,0,2,0,3,13,8,-34,7,9,42,18,26,-5,54,11,-94,-46,-128,4,48,52,0,0,0,0,0,0,0,0,0,0,0,0,1,1,-32,-80,0,98,-5,71,0,64,0,0,0,0,0,0,0,0,0,-116,1,104,2};
对于(int i=0;i>>1);
}
}
}
System.out.println(Integer.toUnsignedString(crc_));
}
}

谢谢你的回答。但现在它返回47而不是44。我在回答中提到的所有更正?在这四个地方?“crc”在C代码中是否初始化为crc_预置?是的,我猜是>>>而不是EJPs同步应答中的>>。这里的语义不同,因为java不像C那样具有“未签名”类型。它有时也会在使用较小的字体时进行注释。现在,当我切换到>>>并用0xff@AlexanderCiesielski如果您对我的答案发表评论,请在我的答案下发表评论。
If((crc&0x01)==0x01)crc=((crc>>1)和0xff)^crc\u POLYNOM;else crc=(crc>>1)&0xff;}返回crc我用0xff屏蔽了三次右移。现在返回75。@AlexanderCiesielski继续观察,我会发布表代码,但今晚可能不会,现在是我的时间10:30。将“更新(int)”替换为:public void update(int b){update(ByteBuffer.allocate(Integer.BYTES).putin(b.array(),0,Integer.BYTES);}
if (crc & 0x01)
if ((crc & 0x01) != 0)
if ((crc & 0x01) == 0x01)
#include <stdio.h>

#define CRC_POLYNOM 0x9c
#define CRC_PRESET 0xFF

int main() {
    unsigned int crc = CRC_PRESET;
    unsigned char FRAME[] = {1, 56, -23, 3, 0, 19, 0, 0, 2, 0, 3, 13, 8, -34, 7, 9, 42, 18, 26, -5, 54, 11, -94, -46, -128, 4, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, -32, -80, 0, 98, -5, 71, 0, 64, 0, 0, 0, 0, -116, 1, 104, 2};
    for(int i = 0; i < sizeof(FRAME); i++) {
        crc ^= FRAME[i];
        for(int j = 0; j < 8; j++) {
            if(crc & 0x01) {
                crc = (crc >> 1) ^ CRC_POLYNOM;
            } else {
                crc = (crc >> 1);
            }
        }
    }
    printf("%u\n", crc);
    return 0;
}
package demo;

public class DemoTranslation {
    public final static int CRC_POLYNOM = 0x9c;

    public final static int CRC_PRESET = 0xFF;

    public static void main(String[] args) {
        int crc_U = CRC_PRESET;
        byte[] frame_U = {1, 56, -23, 3, 0, 19, 0, 0, 2, 0, 3, 13, 8, -34, 7, 9, 42, 18, 26, -5, 54, 11, -94, -46, -128, 4, 48, 52, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, -32, -80, 0, 98, -5, 71, 0, 64, 0, 0, 0, 0, -116, 1, 104, 2};
        for(int i = 0; i < frame_U.length; i++) {
            crc_U ^= Byte.toUnsignedInt(frame_U[i]);
            for(int j = 0; j < 8; j++) {
                if((crc_U & 0x01) != 0) {
                    crc_U = (crc_U >>> 1) ^ CRC_POLYNOM;
                } else {
                    crc_U = (crc_U >>> 1);
                }
            }
        }
        System.out.println(Integer.toUnsignedString(crc_U));
    }
}