【发布时间】:2017-04-20 11:38:36
【问题描述】:
我正在实施 rolling 版本的 adler32 checksum。
这个answer 有助于仔细检查我的数学。但是我正在努力在 golang 中正确实现它。
我写了以下代码:
func roll(adler, n, leave, enter uint32) uint32 {
a := adler & 0xffff
b := adler >> 16
a = (a + enter - leave) % MOD
b = (b - n*leave - 1 + a) % MOD
return b<<16 | a
}
它在各种输入上进行了测试,并且运行良好,直到我决定在随机数据上运行它。这是一个sample,它不起作用(我找到了几个)。
让我困惑的是,python 中的相同代码可以完美地处理这些输入:
def roll(adler, n, leave, enter):
a = adler & 0xffff
b = adler >> 16
a = (a + enter - leave) % MOD
b = (b - n*leave - 1 + a) % MOD
return b<<16 | a
为了更好的衡量标准,我包括proof 这在 python 中有效。请注意,python 校验和与 go 校验和的非滚动版本匹配(并且该部分直接来自 go 核心库)。
我研究了所有其他有问题的样本的结果,发现我从未在校验和的最低有效位(“a”位)上犯错。此外,错误始终相同,等于0xe10000。我怀疑 go 如何处理对 uint32 整数的模运算的特殊性是造成这种情况的原因。
发生了什么以及如何修复我的代码?
【问题讨论】:
-
你的减法正在回绕。
-
你将如何修复代码?
-
如果您在计算 b 时应用 32 位掩码,您会在 Python 代码中得到相同的差异 (0xe10000),如下所示:
b = ((b - (n*leave) - 1 + a) & 0xffffffff) % MOD
标签: python go checksum modulo adler32