我正在尝试将此C ++校验和转换为Java,但暂时我失败了。我做错了什么?
该怎么办? 它应该在OpenGL
中返回缓冲区的正校验和这是C部分。
DWORD QuickChecksum(DWORD *data, int size){
if(!data) {
return 0x0;
}
DWORD sum;
DWORD tmp;
sum = *data;
for(int i = 1; i < (size/4); i++)
{
tmp = data[i];
tmp = (DWORD)(sum >> 29) + tmp;
tmp = (DWORD)(sum >> 17) + tmp;
sum = (DWORD)(sum << 3) ^ tmp;
}
return sum;
}
以下是我在Java中尝试过的内容。据我所知,DWORD是32位所以我在一个long中使用int得到一个unsigned int,这应该在java中使用&gt;&gt;&gt;?
我一直在看这个问题,因为我已经对它视而不见了。
public static long getChecksum(byte[] data, int size) {
long sum, tmp;
sum = getInt(new byte[]{data[0], data[1], data[2], data[3]},true) & 0xFF;
for(int I = 4; I < data.length; I += 4)
{
tmp = getInt(new byte[]{data[I],data[I+1],data[I+2],data[I+3]},true) & 0xFF;
tmp = (sum >>> 29) + tmp;
tmp = (sum >>> 17) + tmp;
sum = (sum << 3) ^ tmp;
}
return sum & 0xFF;
}
private static int getInt(byte[] bytes, boolean big) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
return bb.getInt();
}
谢谢大家的帮助!
答案 0 :(得分:1)
明显的错误是,在三个地方,你和输入字以及最后的校验和0xff
,丢失了高24位。据推测,您正在尝试将long
值减少到32位,这需要AND与0xffffffffL
。在执行此操作之前,您还需要将getInt()
的返回值转换为long
,否则您仍会获得您要避免的符号扩展名。
我的Java有点生疏,但我相当肯定只要你使用int
进行右移,你就可以坚持>>>
得到正确的结果(就像你一样)做)。
你也有一个错误,你无条件地读取前四个字节而不检查输入是否为空。
您还需要确保输入具有4个字节的倍数;要么通过检查长度,要么通过更改它来使用int[]
而不是{C}版本的byte[]
。当然,不需要size
参数,因为Java数组随身携带它们的大小。
以下内容应与C版本具有相同的结果:
public static int checksum(int[] data)
{
if (data.length == 0) {
return 0;
}
int sum = data[0];
for (int i = 1; i < data.length; ++i) {
int tmp = data[i];
tmp = (sum >>> 29) + tmp;
tmp = (sum >>> 17) + tmp;
sum = (sum << 3) ^ tmp;
}
return sum;
}
答案 1 :(得分:0)
在Java中,>>>
执行无符号移位,这意味着它会将位值0插入到移入的新位中,将负数转换为正数。有符号移位>>
扩展符号位,负值为1,因此负数保持为负数。
要修复您的代码,请至少将0xFF
替换为&amp;中的0xFFFFFFFF
。操作。此外,我认为您每次分配到tmp
和sum
时都可能必须这样做,而不是仅仅在循环后一次(不是100%肯定,必须通过代码查看是否正确)比特得到保留,即使没有ANDing也没有额外的位潜入,所以比抱歉更安全。
我还在方法中首先添加:
if (data.length & 3 != 0)
throw new IllegalArgumentException("byte buffer size not multiple of 4");
此外,我要么删除size
参数,要么实际使用它而不是data.length
(在检查它有效之后),以防数据可能包含比您想要处理的更多的字节。
答案 2 :(得分:0)
C ++版本返回sum
的32位,但您的Java版本只有& 0xFF
,只剩下8位。
>>>
执行无符号移位,并定义所有其他操作,以便它们在签名Java类型中的结果等于C ++无符号类型上的相同操作,除了对有符号位的解释。所以你可以在这里使用int
。long
,则需要使用& 0xFFFFFFFF
获取32位。