• C语言位操作奇偶校验算法


         信息是以比特流的方式传输的,类似01000001。在传输过程中,有可能会发生错误,比如,我们存储了01000001,但是取出来却是01000000,即低位由0变成了1。为了检测到这种错误,我们可以通过“奇偶校验”来实现。假如,我们存储的数据是一个字节,8个比特位,那我们就可以计算每个字节比特位是1的个数,如果是偶数个1,那么,我们就把第九个位设为1,如果是奇数个1,那么就把第九个位设为0,这样连续9个字节比特位为1的位数肯定是奇数。这中方法叫做“奇校验”,“偶校验”和此类似。当然,在实际应用中,也可以把一个字节的前7位作为数据位,最后一个为作为校验位。

    1、奇偶校验的常规方法:

    unsigned int v;       // 待检测的数字
    bool parity = false;  //初始判断标记
    while (v)
    {
      parity = !parity;
      v = v & (v - 1);
    }

    通过while循环,每执行一次,v中1的数目就会减少1,如果v中1的数目为奇数,则parity=true,否则parity=false。

    2、通过构建字典表进行奇偶校验:

    static const bool ParityTable256[256] = 
    {
    #   define P2(n) n, n^1, n^1, n
    #   define P4(n) P2(n), P2(n^1), P2(n^1), P2(n)
    #   define P6(n) P4(n), P4(n^1), P4(n^1), P4(n)
        P6(0), P6(1), P6(1), P6(0)
    };

    通过嵌套宏定义,制作一张包括0~255各个数字中包含1的个数,其中包含偶数个1,则ParityTable256[i]=0,否则ParityTable256[i]=1;

    如果要判定char类型的b中i的个数的奇偶,可以直接使用下面的代码:

    unsigned char b;  
    bool parity = ParityTable256[b];

    而对于32-bit的数,则使用下面的代码:

    unsigned int v;
    v ^= v >> 16;
    v ^= v >> 8;
    bool parity = ParityTable256[v & 0xff];

    原理:

    (1)通过v^=v>>16,将v中的低16位与高16位进行按位或(^)操作, 相当于0~16位保留1的总个数的奇偶与v中的1的总  个数的奇偶相同;

    (2)通过v^=v>>8,将v中的9~16位与0~8位进行按位或(^)操作,相当于0~8位保留1的总个数的奇偶与0~16中1的总个数的奇偶相同;

    (3)通过(1)(2)操作,最初v中1的总个数的奇偶与最后v中1~8位中1的总个数的奇偶相同,v&0xff相当于获取v中1~8比特位的1,然后再查表即可。

    或者使用如下的代码:

    unsigned char * p = (unsigned char *) &v;
    parity = ParityTable256[p[0] ^ p[1] ^ p[2] ^ p[3]];

    原理:取v的地址,并进行强制类型转换为char*,

    e.g. v=1234

    二进制表示为:

    00000000 00000000 00000100 11010010

    p[0]:11010010

    p[1]:00000100

    p[2]:00000000

    p[3]:00000000

        ^------------

           11010110

     通过p[0] ^ p[1] ^ p[2] ^ p[3]] 操作,将p[i]中的所有的1都放在一个8位的数中,然后查表即可

    3、使用64位乘法与模除法进行奇偶校验

    unsigned char b;
    bool parity = 
      (((b * 0x0101010101010101

    原理:
    0x0101010101010101ULL://0000 0001 0000 0001 0000 0001 0000 0001 0000 0001 0000 0001 0000 0001 0000 0001

    0x8040201008040201ULL://1000 0000 0100 0000 0010 0000 0001 0000 0000 1000 0000 0100 0000 0010 0000 0001

    0x1FF :  //0001 1111 1111

     b * 0x0101010101010101ULL  将1~8位设置为b的二进制比特位,

  • 相关阅读:
    【Web】JavaScript 语法入门
    tar 和gzip 的区别
    状态码,好记
    PyCharm与git/GitHub取消关联
    在Ubuntu下安装deb包需要使用dpkg命令
    linux每日命令(4):解压命令
    Python之os.path.join()
    Python的JAVA胶水——jpype
    python之chardet验证编码格式
    python之arrow时间处理模块
  • 原文地址:https://www.cnblogs.com/cpoint/p/3367375.html
Copyright © 2020-2023  润新知