位运算看这篇就够了 ~~让我康康

707 阅读2分钟

计算原理

现代计算机只能处理二进制数据。包括基本的加减乘除都是通过二进制运算来完成的。
只是二进制不方便程序猿→_→记忆,后来各位仙人大佬就各出奇招。汇编语言出现,A、B、C语言等相对高级的语言也相继出现。

由于二进制更加贴近硬件,能更好的针对硬件优化,这就是为什么汇编大部分时候会快于C等高级语言的原因。 当然在高级语言中,我们也可以适当的运用位运算来提高程序的性能。

例如可以通过下列语句判断一个数字的奇偶性

void test(int x)
{
    if (x & 1) {
        printf("奇数");
    } else {
        printf("偶数");
    }
}

具体原理看下面

位运算符

运算 操作符 示例
左移(低位补0) << 0011 => 0110
右移(正数右移,高位用补0,负数右移,高位用补1) >> 0110 => 0011
无符号左移(低位补0) <<< 1111 => 1110
无符号右移(高位补0) >>> 1111 => 0111
按位或 | 0011 | 1011 => 1011
按位与 & 0011 & 1011 => 1011
按位取反 ~ 0011 => 1100
按位异或 (相同为零不同为一) ^ 0011 ^ 1011 => 1000

求绝对值

int v; 
unsigned int r;  // 绝对值
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

例如+7(00000111) 8位, 计算出mask=00000000;

(00000111 + 00000000) ^ 00000000 => 00000111

正数的绝对值是它本身!

如果是-7(11111001), 计算出mask=11111111;

(11111001 + 11111111) ^ 11111111 => 00000111

负数绝对值等于正数!

判断奇偶性

void test(int x)
{
    if (x & 1) {
        printf("奇数");
    } else {
        printf("偶数");
    }
}

1的二进制是 000...00001; 任何数和它进行 & 操作第一位以上的位都会变成0, 由于x是进行二进制运算, 所以最低位1为奇数,0为偶数。

交换值

// 不使用中间变量交换变量值
void swap(int x , int y) 
{ 
    x ^= y; 
    y ^= x; 
    x ^= y; 
} 

取模运算

int mod(int n, int s) 
{
    unsigned int d = 1 << s; // d是2的幂次方 1, 2, 4, 8, 16, 32, ...
    return n & (d - 1); //等价于 n % s
}



参考
en.wikipedia.org/wiki/Assemb…
graphics.stanford.edu/~seander/bi…