在查看计算正在运行的校验和时需要澄清。
假设我有这样的数据。
data = 'helloworld'
假设块大小为5,我需要计算运行校验和。
>>> zlib.adler32('hello')
103547413
>>> zlib.adler32('ellow')
105316900
根据Python文档(python版本2.7.2)
zlib.adler32(data[, value])
“计算Adler-32校验和数据。(Adler-32校验和差不多 与CRC32一样可靠但可以更快地计算出来。)如果 值存在,它用作校验和的起始值; 否则,使用固定的默认值。这允许计算a 在几个输入的串联上运行校验和。“
但是当我提供这样的东西时,
>>> zlib.adler32('ellow', zlib.adler32('hello'))
383190072
输出完全不同。
我尝试创建自定义函数来生成rsync算法中定义的滚动校验和。
def weakchecksum(data):
a = 1
b = 0
for char in data:
a += (ord(char)) % MOD_VALUE
b += a % MOD_VALUE
return (b << 16) | a
def rolling(checksum, removed, added, block_size):
a = checksum
b = (a >> 16) & 0xffff
a &= 0xffff
a = (a - ord(removed) + ord(added)) % MOD_VALUE
b = (b - (block_size * ord(removed)) + a) % MOD_VALUE
return (b << 16) | a
以下是我运行这些函数所获得的值
Weak for hello: 103547413
Rolling for ellow: 105382436
Weak for ellow: 105316900
正如您所看到的,就价值而言,我在滚动校验和和python的实现方面存在巨大差异。
我在计算滚动校验和时出错了? 我是否正确使用了python的adler32函数的滚动属性?
答案 0 :(得分:5)
在您的方法“滚动”中,
b = (b - (block_size * ord(removed)) + a) % MOD_VALUE
应该是
b = (b - (block_size * ord(removed)) + a - 1) % MOD_VALUE
根据维基百科中adler32算法的解释,我们可以看到:
A = 1 + D1 + D2 + ... + Dn (mod 65521)
B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
= n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n (mod 65521)
Adler-32(D) = B × 65536 + A
当我们滚动校验和时,我们将得到等式:
A1 = (1 + D2 + D3 + … + Dn + Dn+1)(mod 65521)
= (1 + D1 + D2 + D3 + … + Dn) – D1 + Dn+1(mod 65521)
= A – D1 + Dn+1(mod 65521)
B1 = (1 + D2) + (1 + D2 + D3) + … + (1 + D2 + D3 + … + Dn + Dn+1)(mod 65521)
= (1 + D1) – D1 – 1 + (1 + D1 + D2) – D1 + ... +(1 + D1 + D2 + … + Dn) – D1 + (1 + D1 + D2 + … + Dn + Dn+1) – D1(mod 65521)
= B – nD1 – 1 + A1 + D1 – D1(mod 65521)
= B – nD1 + A1 – 1(mod 65521)
答案 1 :(得分:4)
adler32()
函数不提供“滚动”。文档正确地使用了“running”(不是“滚动”)这个词,这意味着它可以简单地计算出块中的adler32,而不是一次性计算。您需要编写自己的代码来计算“滚动”的adler32值,该值将是数据滑动窗口的adler32。
答案 2 :(得分:3)
顺便说一句,你的def rolling()是正确的,至少对于模数结果的符号有除数符号的Python。它可能在其他语言中不起作用,例如在C中,%的结果符号可以是被除数的符号,也可以是实现定义的。
您可以通过考虑在每一步可以获得的模数65521的距离,以及将%替换为if和65521的加法或减法,或者使用足够大的数据类型来让它变为高效,从而提高算法的效率。虽然并且弄清楚你很少能在总和上获得%以避免溢出。再次,小心对负股息的百分比。
答案 3 :(得分:1)
这是工作功能。请注意MOD的计算步骤。
def myadler32(data):
a = 1
b = 0
for c in data:
a += c
b += a
a %= MOD_ADLER
b %= MOD_ADLER
return b<<16 | a
答案 4 :(得分:0)
我相信您在测试中错误计算了adler32值:
>>> import zlib
>>> zlib.adler32("helloworld")
389415997
>>> zlib.adler32("world",zlib.adler32("hello"))
389415997