Sword 位运算取余操作

/* 位运算取余操作 */

#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <assert.h>

void test1()
{
    unsigned a = 12;
    unsigned b = 7;
    unsigned c = 0;

    c = a % b;

    printf("----[%u]---\n", c);
}

void test2()
{
    unsigned a = 12;
    unsigned b = 32;
    unsigned c = 0;

    /*
    设计说明:
        位运算取余必要条件
            要求除数必须是2的幂次方
    */
    c = a & (b - 1);

    printf("----[%u]---\n", c);
}

int main()
{
    test2();
    getchar();
    return 0;
}

 

向上求一个数最近的2的整数次幂

// 方法一
static unsigned int _shared_dict_next_power(unsigned int size)
{
    unsigned long i = 1;

    while (1)
    {
        if (i >= size)
        {
            return i;
        }

        i *= 2;
    }
}

 

方法二

思路分析
2的n次方的二进制信息是如何表示的呢?他的二进制表现形式为,在第n位置上为1,其他位置全部为0。
例如 num的二进制是 10101001 ,那么距离num最近的2的n次方是多少呢?只需要把num的二进制最高位的1往前移动一位,也就是 100000000。
那么如何得到这个数呢?我们把100000000这个数减去个1来看下,得出的结果为011111111,这个数和num的二进制 10101001 最高位的1是一样的,只是右边全部为1。
那么接下来只需要把num的二进制信息最高位1右边变成1就可以了。
这里用到的是或运算,或运算的规则为1|1=1、1|0=1、0|0=0。
我们不知道num的数值是多少,他的最高位的1有可能在0~31位的任何位置,所以要做好最坏的打算。

第一轮
10101001 >> 1,即将最高位的1移动到次高位上,然后两数进行或计算,那么现在最高位和次高位肯定都是1
10101001 | (10101001 >> 1) = 11111101
第二轮
11111101 >> 2 目前最高位和次高位都是1,因此右移2,然后进行或运算,那么最高位加上后面3位肯定都是1
11111101 | (11111101 >> 2) = 11111111

按照这个思想,不断右移,进行与运算,当右移16时,基本上31都是1了

static unsigned int pow2roundup(unsigned int size)
{
    // 防止遇到 size本身就是2的幂
    size--;

    size |= size >> 1;
    size |= size >> 2;
    size |= size >> 4;
    size |= size >> 8;
    size |= size >> 16;

    return size + 1;
}

 

posted on 2019-11-19 19:55  寒魔影  阅读(211)  评论(0编辑  收藏  举报

导航