我在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);
}
}
我设法做的是 Java :
public static long calculateCRC8(byte[] b, int len) {
long crc = CRC_PRESET;
for (int i = 0; i < len; i++) {
crc ^= b[i];
for (int j = 0; j < 8; j++) {
if ((crc & 0x01) == 0)
crc = (crc >> 1) ^ CRC_POLYNOM;
else
crc = crc >> 1;
}
}
return crc;
}
对于示例字节数组:
byte[] b = new byte[] {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};
C 代码返回 29 ,但我的 Java 代码返回 44 。 我做错了什么?
我认为这是因为Java的只签名数据类型,所以如何解决这个问题呢?
答案 0 :(得分:6)
if (crc & 0x01)
测试是否设置了最低位。
if ((crc & 0x01) == 0)
这测试底部位是否清除。
您还应该在Java代码中使用无符号右移(即>>>
而不是>>
,在两个地方),并在返回之前使用0xff
屏蔽结果。< / p>
编辑最后你需要改变这个:
crc ^= b[i];
到此:
crc ^= b[i] & 0xff;
但是你应该把它扔掉,然后查看表格驱动的方法。它的速度是此速度的八倍。
EDIT 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));
}
}
答案 1 :(得分:2)
您的“^”实际上已经像箭头一样指向错误的部分
相当于
if (crc & 0x01)
Java中的(因为java需要在if中使用布尔表达式)
if ((crc & 0x01) != 0)
或
if ((crc & 0x01) == 0x01)
答案 2 :(得分:1)
我为您的问题创建了一个完整的/独立的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;
}
这里是在https://www.mtsystems.com上自动创建的等效Java代码:
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));
}
}