位运算、原码、反码、补码
位运算的地位
以下内容摘自《枕边算法书》感觉对于位运算描述的很形象
对于程序员来说,”位” 相当于现实世界中构成水和空气的粒子。
编程世界的所有东西都会从位开始,以位结束。刚步入编程世界的
初学者看到整数就是整数,看到字符串就是字符串。但功力深厚的
程序员眼中无论整数还是字符串,它们都是位。
与系统编程不同,一般应用程序的编程对位运算的要求并不高。
即使如此,很少有程序员不懂位运算,因为在不懂位运算的情况下
编程写程序,就像在现实世界中不呼吸、不喝水一样,几乎不可能。
位运算的类型
| 运算符 | 含义 |
|---|---|
| & | 按位与:全1才1,否则都0 |
| | | 按位或:有1得1,全0才0 |
| ^ | 按位异或:相异为真,相同为假 |
| >> | 右移:对于有符号数的右移分为算术右移和逻辑右移 |
| << | 左移:比较简单不论是否有符号整数 |
| ~ | 取反:每个位1变0,0变1 |
| 对于正整数而言,左移1位就是x2,右移就是除2 | |
| 下图来自《Computer Systems - A Programmer’s Perspective》 | |
| 算术右移:直接右移n位,左侧空出来的n位全补0 | |
| 逻辑右移:对于有符号数有些不同,对于无符号数没有区别 | |
| 可惜对于右移而言标准c没有规定,应该使用哪种,大多数的编译器都使用算术右移 | |
| java中明确规定x>>k运算符表示x算术右移k位, x>>>k表示逻辑右移 |
原码
一个数的二进制表示加上正负号
反码(Ones’ complement /一的补码)
定义
式中,N为真值,n为编码的位数
反码,正数的反码等于其原码,而负数的反码则可以通过保留其符号位,将原码的数值位取反得到。
补码(Twos’ complement /二的补码)
计算机中采用补码的原因是原码和反码的时候,0的表示不唯一
补码的计算方法
正数的补码和原码一致,辅助的补码用用其绝对值的原码按位取反,然后(从LSB(最低有效位))+1
根据补码(2补数)求真值的方法
设1100为补码, 拿到补码最高位是-(2^3), 然后 + 2^2 得到 -4
总结
1. 现代计算机中存储的永远是补码
2. 运算的时候也是用补码在运算
3. x,y均为整数, 如果有~x = y 成立,则有 x + y = -1 成立
例题
- ~3 = ?
3 = (0000 0011)按位取反得到(1111 1100) 按照2补数解释为-4 1
2
3int cat = 13;
cat - ~-cat; // this experssion's value is 1
putchar (~-~-~-cat); // this line equal to putchar('\n'); \n 的ascii code 十进制的值为 10
位运算可以用来判断整数的奇偶性
1 | // 输出0 ~ 100 的所有奇数 |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.