adler32滚动校验和-python计算的差异
在计算运行校验和时需要澄清adler32滚动校验和-python计算的差异,python,adler32,Python,Adler32,在计算运行校验和时需要澄清 >>> zlib.adler32('hello') 103547413 >>> zlib.adler32('ellow') 105316900 假设我有这样的数据 data = 'helloworld' 假设blocksize为5,我需要计算运行校验和 >>> zlib.adler32('hello') 103547413 >>> zlib.adler32('ellow') 105316900
>>> zlib.adler32('hello')
103547413
>>> zlib.adler32('ellow')
105316900
假设我有这样的数据
data = 'helloworld'
假设blocksize为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
正如您所看到的,我的滚动校验和实现与python的实现在价值上有很大的不同
我在计算滚动校验和时哪里出错了?
我是否正确地使用了python的adler32函数的滚动特性?我相信您在测试中错误地计算了adler32值:
>>> import zlib
>>> zlib.adler32("helloworld")
389415997
>>> zlib.adler32("world",zlib.adler32("hello"))
389415997
我相信您在测试中错误计算了adler32值:
>>> import zlib
>>> zlib.adler32("helloworld")
389415997
>>> zlib.adler32("world",zlib.adler32("hello"))
389415997
adler32功能不提供滚动。文档正确地使用了running not rolling这个词,这意味着它可以分块计算adler32,而不是一次计算所有adler32。您需要编写自己的代码来计算滚动adler32值,该值将是数据上滑动窗口的adler32。adler32函数不提供滚动。文档正确地使用了running not rolling这个词,这意味着它可以分块计算adler32,而不是一次计算所有adler32。您需要编写自己的代码来计算滚动adler32值,这将是数据上滑动窗口的adler32。顺便说一句,您的def滚动是正确的,至少在Python中,模结果的符号有除数的符号。它可能在其他语言中不起作用,例如,在C语言中,%的结果的符号是红利的符号,或者是实现定义的符号
您可以通过考虑在每一步中距离模65521有多远来提高算法的效率,或者用if和65521的加减来替换%,或者使用足够大的数据类型让它保持一段时间,并计算出在求和中不使用%以避免溢出的频率。同样,要注意负红利的%。顺便说一句,您的def滚动是正确的,至少在Python中,模结果的符号有除数的符号。它可能在其他语言中不起作用,例如,在C语言中,%的结果的符号是红利的符号,或者是实现定义的符号
您可以通过考虑在每一步中距离模65521有多远来提高算法的效率,或者用if和65521的加减来替换%,或者使用足够大的数据类型让它保持一段时间,并计算出在求和中不使用%以避免溢出的频率。同样,要注意负红利的百分比。这里是工作函数。请注意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
这里是工作函数。请注意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
在您的滚动方法中
b = (b - (block_size * ord(removed)) + a) % MOD_VALUE
应该是
b = (b - (block_size * ord(removed)) + a - 1) % MOD_VALUE
根据维基百科对算法的解释,我们可以看到:
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)
在您的滚动方法中
b = (b - (block_size * ord(removed)) + a) % MOD_VALUE
应该是
b = (b - (block_size * ord(removed)) + a - 1) % MOD_VALUE
根据维基百科对算法的解释,我们可以看到:
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)
谢谢但是,我想我是在寻找滚动校验和的差异。在你的例子中,我得到的是'world'的校验和,我感兴趣的是,用'hello'的校验和计算'ellow'的校验和。两者之间的区别在于删除了“h”,添加了“w”。如果我不清楚,请告诉我。谢谢。但是,我想我是在寻找滚动校验和的差异。在你的例子中,我得到的是'world'的校验和,我感兴趣的是,用'hello'的校验和计算'ellow'的校验和。两者之间的区别在于删除了“h”,添加了“w”。如果我不清楚,请告诉我。马克,谢谢你的补充意见。我尝试使用prime 65521,但在我的滚动校验和过程实现中出现了计算错误。检测到或未检测到更改。如果我使用2^16,一切都很好。我希望稍后能够回到这个问题上来,排除编程错误的可能性,同时带来一些关于这个主题的有用信息。马克,谢谢你的补充意见。我尝试了prime 65521,但在我的 滚动校验和过程实现检测到或未检测到更改。如果我使用2^16,一切都很好。我希望稍后能够回到这个问题上来,同时排除编程错误的可能性,带来一些关于这个主题的有用信息。