《算法》Adler-32校验和算法
Posted Bruceoxl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》Adler-32校验和算法相关的知识,希望对你有一定的参考价值。
Adler-32是Mark Adler在1995年提出的一种校验算法,该算法在FastLZ、zlib 等压缩算法中被广泛使用。
Adler-32算法和32位CRC算法相比具有更快的执行效率,但这两者的安全性都不高。Adler-32的可靠性介于fletcher-16和fletcher-32之间,在输入较短的消息时Adler-32变得很不可靠。
1 Adler-32算法描述
Adler-32算法通过计算两个16位校验和A和B并将它们的位连接成32位整数来获得Adler-32校验和。
在Adler-32运行开始时,A初始化为1,B初始化为0.总和以模数65521(小于216的最大素数)完成。字节以网络顺序(大端)存储,B占用两个最重要的字节。
假设我们要得到D的Adler-32校验码,n是D的长度(以字节为单位).那我们可以用以下公式来取得:
以Wikipedia中的实例来具体说明Adler-32算法实现过程。
最后A = 92010 = 38916,B = 458210 = 11E616
因此,最终的校验和结果为11E6039816。
2 Adler-32算法实现
Adler-32算法很简单,Wikipedia也有实例,下面就根据Adler-32的算法描述来实现Adler-32算法。
【C语言实现】
/**
******************************************************************************
* @file main.c
* @author BruceOu
* @version V1.0
* @date 2021-09-06
* @blog https://blog.bruceou.cn/
* @Official Accounts 嵌入式实验楼
* @brief
******************************************************************************
*/
/**Include*********************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
//
const uint32_t MOD_ADLER = 65521;
/**
* @brief adler32
* @param pData, unLen
* @retval unCheckSum
*/
uint32_t adler32(uint8_t *pData, size_t unLen)
{
uint32_t s1 = 1, s2 = 0;
size_t ulIndex;
uint32_t unCheckSum = 0 ;
// Process each byte of the data in order
for (ulIndex = 0; ulIndex < unLen; ++ulIndex)
{
s1 = (s1 + pData[ulIndex]) % MOD_ADLER;
s2 = (s2 + s1) % MOD_ADLER;
}
unCheckSum = (s2 << 16) | s1;
return unCheckSum;
}
/**
* @brief main
* @param None
* @retval int
*/
int main()
{
char chData[] = "Wikipedia";
uint32_t unResult = 0;
unResult = adler32(chData, strlen(chData));
printf("result : %x", unResult);
return 0;
}
运行结果如下:
和理论值是相符的。
以上代码是Adler-32算法的直接实现,效率不高,改进后如下:
/**
* @brief adler32
* @param unCheckSum, pBuf, nLen
* @retval unCheckSum
*/
static uint32_t adler32(uint32_t unCheckSum, const void* pBuf, size_t nLen)
{
const uint8_t* ptr = (const uint8_t*)pBuf;
uint32_t s1 = unCheckSum & 0xffff;
uint32_t s2 = (unCheckSum >> 16) & 0xffff;
while (nLen > 0)
{
uint32_t k = nLen < 5552 ? nLen : 5552;
nLen -= k;
while (k >= 8)
{
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
s1 += *ptr++;
s2 += s1;
k -= 8;
}
while (k-- > 0)
{
s1 += *ptr++;
s2 += s1;
}
s1 = s1 % MOD_ADLER;
s2 = s2 % MOD_ADLER;
}
return (s2 << 16) + s1;
}
最后结算的结果都是一样的。
欢迎访问我的网站
BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书
BruceOu的知乎
欢迎订阅我的微信公众号
以上是关于《算法》Adler-32校验和算法的主要内容,如果未能解决你的问题,请参考以下文章