位运算操作相关

    位操作

    在压缩和解压数据时,常常需要在小于一个字节的数量级上 进行数据操作。因此,在讨论各种数据压缩方法之前,首先必须熟悉一些对数据位进行的操作。这些操作非常重要,因为C语言本身只有一小步等内在的、不可分割的操作数。下面是介绍一些位操作的基础,和参阅博客:位操作基础篇之位操作全面总结

      下面是自己对博客内容简单的总结。

     
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <stdbool.h>

/*位运算小技巧*/
/*1、判断奇偶*/

#define IS_EVEN(n) {printf("number %d is:",(n));\
    (n) & 1 == 1?printf("奇数\n"):printf("偶数\n");}

/*2、数据交换*/

#define SWAP(a,b) { if (*a != *b){ \
                         *a ^= *b;\
                         *b ^= *a;\
                         *a ^= *b;\
                     }\
                  }

/*3、交换符号,就是将整数变为负数,负数变为整数*/

#define SIGN_REVERSAL(n) (~(a) + 1)

/*4、求绝对值*/

#define ABS(n) ((n) >> 31 == 0?(n):(~(n) + 1))

/*5、0到100中刷选素数方法*/
#define  MAXN  100
bool flag[MAXN];
int primes[MAXN/3 + 1],pi = 0;

void getPrime_1()
{
    int i,j;
    memset(flag,false,sizeof(flag));
    for(i = 2;i < MAXN; i++){
        if(!flag[i]){
            primes[pi++] = i;
            for(j = i; j < MAXN; j += i){
                flag[j] = true;
            }
        }
    }    
}
void PrintfArray()
{
    int i = 0;
    for(; i < pi; i++)
        printf("%d ",primes[i]);
    puts("");
}
/*位压缩筛选素数
 *其方法和上面的一样,只是在flag中用位来对应素数的位置
 *
 * */
int flag_2[MAXN/32];
void getPrime_2()
{
    int i,j;
    pi = 0;
    memset(flag_2,false,sizeof(flag_2));
    for(i = 2;i < MAXN; i++){
        if(!((flag_2[i/32] >> (i%32)) & 1)){
            primes[pi++] = i;
            for(j = i; j < MAXN; j += i){
                flag_2[j/32] |= (1<<(j%32));
            }
        }
    }    

}


int main()
{
    IS_EVEN(20);
    int a = 10,b=20;
    printf("交换前:a = %d,b = %d\n",a,b);
    SWAP(&a,&b);
    printf("交换后:a = %d,b = %d\n",a,b);
    printf("a = %d,SIGN_REVERSAL(a) = %d\n",a,SIGN_REVERSAL(a));
    printf("ABS(a) = %d\n",ABS(a));

    puts("用筛素数法求100以内的素数");
    getPrime_1();
    PrintfArray();
    puts("用位运算筛素数法求100以内的素数");
    getPrime_2();
    PrintfArray();
    return 0;
}

下面是数据压缩和解压中经常 遇到的位操作函数介绍

/*bit.c*/
#include <string.h>
#include <stdio.h>

/****************************************************************
 *获取bis中处于位置pos的位的状态。
 *返回值:相应位的状态:1or0。
 ***************************************************************/
int bit_get(const unsigned char * bits, int pos)
{
    unsigned char mask;
    int       i;
    /*设置掩码*/
    mask = 0x80;

    for (i = 0; i < (pos % 8); i ++)
        mask = mask >> 1;
    /*获得当前位的数值*/
    return (((mask & bits[(int)(pos / 8)]) == mask )? 1:0);
}

/**********************************************************
 *设置bits中处于pos的位的状态(根据state的数值来设置)。
 *最左边位置位0,状态值必须为0或1;
 *无返回值
 * ******************************************************/
void bit_set(unsigned char * bits, int pos, int state)
{
    unsigned mask;
    int i;

    mask = 0x80;

    for (i = 0; i < (pos % 8); i ++)
        mask = mask >> 1;

    if (state)
        bits[pos/8] |= mask;
    else
        bits[pos/8] &= (~mask);

    return;
}

/********************************************************************
 *对bist1与bist2进行异或运算,结果保存到bitsx,
 *无返回值 
 * *****************************************************************/
void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx,int size)
{
    int i;

    for (i = 0 ; i < size; i++){
        if(bit_get(bits1,1) != bit_get(bits2, 1)){
            bit_set(bitsx,i,1);
        } else {
            bit_set(bitsx,i,0);
        }
    }
    return;
}

/****************************************************************
 *将bits进行轮转,将位值向左移count位,操作完成后,处于最左端的
 *count位移动到最右端,而且其他位也相应的轮移
 * 无返回值
 * **************************************************************/
void bit_rot_left(unsigned char *bits,int size, int count)
{
    int fbit,
        lbit,
        i,
        j;

    if (size > 0){
        for ( j = 0; j < count; j++){
            for(i=0;i<=((size - 1)/8);i++){
                lbit = bit_get(&bits[i],0);
                if (i == 0)
                    fbit = lbit;
                else
                    bit_set(&bits[i - 1],7,lbit);
                bits[i] = bits[i] << 1;

            }
            bit_set(bits,size-1,fbit);
        }
    }
}

int main()
{
    unsigned char a ='A' ;
    int i = 0;
    unsigned char b[]={'Z','B','C','D'};

    printf("获得‘A’的值是:");
    /*打印出来应该是01000001 0x41*/
    for(i=0;i<8;i++){
        printf("%d",bit_get(&a,i));
    }


    bit_set(&a,4,1);
    /*设置完的数值应该为01001001 0x49 'I'*/
    printf("\n ###%s() ,%d = %c\n",__FUNCTION__,a,a);

    bit_rot_left(b,9,2);

    printf("%s\n",b);

}

其中对函数bit_rot_left()具体的功能有点模糊,测试几遍还是未能理解!有知道的麻烦给具体解答下!


你可能感兴趣的:(位操作,数据压缩)