在计算正在运行的校验和时,需要进行澄清。
假设我有这样的数据。
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一样可靠,但可以更快地计算。)如果存在值,则将其用作校验和的起始值;否则,将使用固定的默认值。这允许在连接多个输入时计算正在运行的校验和。”
但当我提供这样的东西时,
>>> 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函数的滚动特性?
发布于 2012-03-14 19:17:33
adler32()函数不提供“滚动”。文档正确地使用了“运行”(而不是“滚动”)这个词,这意味着它可以以块的形式计算adler32,而不是一次计算全部。您需要编写自己的代码来计算“滚动”adler32值,这将是数据上方滑动窗口的adler32。
发布于 2013-11-20 02:25:51
在您的方法“滚动”中,
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)发布于 2012-03-15 18:32:45
顺便说一句,def ()是正确的,至少对于Python来说,在Python中,模块化结果的符号带有除数符号。它在其他语言中可能不起作用,例如,在C语言中,%的结果符号要么是派息的符号,要么是定义的实现。
您可以通过考虑在每一步中距离模块65521有多远,或者用if和增减65521替换%,或者使用足够大的数据类型让它持续一段时间,并计算出在总和上获得%以避免溢出的情况,从而提高算法的效率。同样,在负红利问题上要小心。
https://stackoverflow.com/questions/9699315
复制相似问题