关于Fletcher校验和的维基百科文章(目前)对Fletcher 32说the sums need to be reduces after 360 steps。但是,根据我的测试,在720步之后减少就足够了。维基百科的360限制是错误的,还是我在测试中犯了错误?
任何其他可能优化的奖励积分:-)除了硬编码限制外。
我的测试用例(Java,但同样适用于C或C#):
public static void main(String... args) {
byte[] data = new byte[2 * 1024];
Arrays.fill(data, (byte) 255);
for (int limit = 1; limit <= 721; limit++) {
System.out.println("Test limit " + limit);
for (int i = 0; i < data.length; i += 2) {
if (getFletcher32(data, i, 1) != getFletcher32(data, i, limit)) {
System.out.println("Stop at limit=" + limit + " index=" + i);
return;
}
}
}
}
// bytes: the data
// length: the number of bytes (must be an even number)
// limit: when to reduce the sums (only used for testing)
static int getFletcher32(byte[] bytes, int length, int limit) {
int s1 = 0xffff, s2 = 0xffff;
for (int i = 0; i < length;) {
for (int end = Math.min(i + limit, length); i < end;) {
int x = ((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff);
s2 += s1 += x;
}
s1 = (s1 & 0xffff) + (s1 >>> 16);
s2 = (s2 & 0xffff) + (s2 >>> 16);
}
s1 = (s1 & 0xffff) + (s1 >>> 16);
s2 = (s2 & 0xffff) + (s2 >>> 16);
return (s2 << 16) | s1;
}
测试打印:
Test limit 1
Test limit 2
...
Test limit 720
Test limit 721
Stop at limit=721 index=721
意味着对于限制1到720的结果是相同的,并且只有限制721,校验和是不同的(意思是,它是不正确的)。
答案 0 :(得分:1)
我发现我的旧答案非常错误,所以我写了这个简单的循环来检查int
溢出:
long s1 = 0xffff, s2 = 0xffff;
for (int n=0; ; ++n) {
final int a = 0xff;
final int b = 0xff;
final int x = (a << 8) | b;
s2 += s1 += x;
System.out.format("%4d %08X %08X\n", n, s1, s2);
if ((s2 & 0xFFFFFFFFL) != s2) break;
}
输出以
结尾358 0167FE98 FDD3022C
359 0168FE97 FF3C00C3
360 0169FE96 100A5FF59
向我们展示了我们必须在第360次迭代之前停止,以便s2
不会溢出。
所提出的算法有一个区别。这条线
return (s2 << 16) | s1;
应该阅读
return (s2 << 16) | (s1 & 0xffff);
原始类型为uint16_t
,但这并不重要,因为s1
很小。
答案 1 :(得分:1)
我现在意识到自己的错误,并且看到维基百科和我的实施都是正确的......
原因是,维基百科文章使用了360个字(每个字两个字节)的限制,而我的实现使用了720 字节的限制。
至于优化:可能最后的缩减步骤可能会略微简化,但这不会有太大变化。