常用校验和算法
Adler-32校验和
记校验和为\(C\)(32位), 其高16位记为\(s_2\), 低16位记为\(s_1\), 那么有\(C=s_2 * 2^{16} + s_1\). 记有数据字节流\(D[0..len]\) 算法过程如下:
\[\begin{aligned} & s_1 = 1u32 \\ & s_2 = 0u32 \\ & M = 65521(小于65536的最大质数) \\ & \quad \\ & for \quad d \quad in \quad D \\ & \qquad s_1 = (s_1 + d) \mod M \\ & \qquad s_2 = (s_1 + s_2) \mod M \\ & end \\ & \quad \\ & C = s_2 \ll 16 + s_1 \end{aligned} \]
CRC校验
记有生成多项式\(G(x)\)的二进制表示\(g[0..m]\), 有字节流数据\(F(x)\)其二进制位表示为\(f[0..n]\), 记校验和为\(C\)(m-1位), 算法流程如下:
\[\begin{aligned} & C = 0; g=g[0]*2^{0}+g[1]*2^{1}+\cdots+g[m-1]*2^{m-1} \\ & src = 0 \\ & \quad \\ & for \quad bit \quad in \quad f \\ & \qquad src = (src \ll 1) + bit\\ & \qquad if \quad src \ge g \\ & \qquad \qquad src = src \mod g\\ & \qquad end \\ & end \\ & C = src \end{aligned} \]
Fnv算法
Fnv算法目前在用的有两个版本Fnv-1
和Fnv-1a
. 记有校验和\(C\)(共有\(2^{n}\)位), 有字节流数据\(D[0..len]\), 算法流程如下:
- Fnv-1:
\[\begin{aligned} & C = INV \\ & for \quad d \quad in \quad D \\ & \qquad C = C * P \\ & \qquad C = C \oplus d \\ & end \end{aligned} \]
- Fnv-1a:
\[\begin{aligned} & C = INV \\ & for \quad d \quad in \quad D \\ & \qquad C = C \oplus d \\ & \qquad C = C * P \\ & end \end{aligned} \]
- \(x\oplus y\): x异或y;
- INV: 初始Hash值;
- P: 质数;
对于\(C\)不同的位长度, INV和P的值如下:
// 32位
INV = 2166136261;
P = 16777619; // 2^24+2^8+0x93
// 64位
INV = 14695981039346656037;
P = 1099511628211; // 2^40+2^8+0xb3
// 128位
INV = 0x6c62272e07bb014262b821756295c58d;
P = 0x13b+2^88; // 2^88+2^8+0x3b