心算二进制与十进制的转换
- 熟记二进制的特殊数字
| 十进制 | 算法 | 二进制 |
|---|---|---|
| 128 | 2^7 | 1000 0000 |
| 192 | 128 + 2^6 | 1100 0000 |
| 224 | 192 + 2^5 | 1110 0000 |
| 240 | 224 + 2^4 | 1111 0000 |
| 248 | 240 + 2^3 | 1111 1000 |
| 252 | 248 + 2^2 | 1111 1100 |
| 254 | 248 + 2^1 | 1111 1110 |
| 255 | 248 + 2^0 | 1111 1111 |
规律:从128-255,每两个数之间的差是递减的,分别是 2^6 、 2^5 、 2^4 、 2^3 、 2^2 、 2^1 、 2^0
| 十进制 | 算法 | 二进制 |
|---|---|---|
| 1 | 2^0 | 1 |
| 2 | 2^1 | 10 |
| 4 | 2^2 | 100 |
| 8 | 2^3 | 1000 |
| 16 | 2^4 | 1 0000 |
| 32 | 2^5 | 10 0000 |
| 64 | 2^6 | 100 0000 |
| 128 | 2^7 | 1000 0000 |
规律:每个以 1 开头,后面全是 0 的二进制数字对应的十进制数字都是 2^n , n 表示从右往左数 “1” 的位数减一,例: 1000 中, “1” 为第 4 位,对应的十进制数字是 2^(4-1) = 8
2. 将 x (0 <= x < 256) 转为二进制,用以上的特殊数字计算哪些数加起来等于 x ,于是用到了哪些数字,就在对应的位置上写 1 ,其他为 0
3. 例子:
3.1. 将 129 转换为二进制
129 = 128 + 1 ,因为 128 是第 8 位为 1 , 1 是第一位为 1 ,因此 129 的二进制数为 `1000 0001`
3.2. 将 185 转换为二进制
185 = 128 + 32 + 16 + 8 + 1 ,因此 185 的二进制为 `1011 1001`
3.3. 将 244 转换为二进制
244 = 240 + 4 ,因此 244 的二进制为 `1111 0100`
与 (&)
计算式 a & b , a、b 各位中同为 1 才为 1 ,否则为 0
n & (n - 1)表示将n的二进制表示中的最低位为1的改为0
// 求某一个数的二进制表示中1的个数
while (n > 0) {
count++
n &= (n - 1)
}
// 判断一个数是否是二次幂
n > 0 && (n & (n - 1)) === 0
因为 n 的二次幂的二进制数第一位都是 1 ,其后都是 0 ,因此通过 n & (n - 1) 消除掉二进制的 1 之后,自然就变成了 0
一些二进制比较特殊的数字
0x55555555:
0101 0101 0101 0101 0101 0101 0101 0101偶数位为 0 ,奇数位为 1 交替出现0xaaaaaaaa:
1010 1010 1010 1010 1010 1010 1010 1010偶数位为 1 ,奇数位为 0 交替出现0x33333333:
0011 0011 0011 0011 0011 0011 0011 00110 和 1 每隔两位交替出现0xcccccccc:
1100 1100 1100 1100 1100 1100 1100 11001 和 0 每隔两位交替出现0x0f0f0f0f:
0000 1111 0000 1111 0000 1111 0000 11111 和 0 每隔四位交替出现0xf0f0f0f0:
1111 0000 1111 0000 1111 0000 1111 00000 和 1 每隔四位交替出现
或 (|)
计算式 a | b , a、b 各位中有一个为 1 则为 1
非 (~)
将运算符后二进制数反转, 0 变 1 , 1 变 0
异或 (^)
计算式 a ^ b , a、b 对应位相同为 0 ,不同则为 1
根据性质可以得出: a^a=0 , a^0=a,且支持交换律
位移
a << 1 相当于 a * 2 (不超出数值类型范围的情况下)
a >> 1 相当于 a / 2
左移 (<<)
对于数值 3 ,它的二进制为 00011 ,第一位为符号位
| 下标 | 符号位 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|
| 位数 | 0 | 0 | 0 | 1 | 1 |
左移两位 3 << 2 ,注意符号位不参与位移
| 下标 | 符号位 | 3 | 2 | 1 | 0 | ||
|---|---|---|---|---|---|---|---|
| 位数 | 0 | 0 | 0 | 1 | 1 |
高位舍弃,低位补 0 ,结果得 12
| 下标 | 符号位 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|
| 位数 | 0 | 1 | 1 | 0 | 0 |
对于 -3
| 下标 | 符号位 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|
| 位数 | 1 | 1 | 1 | 0 | 1 |
计算机中的负数以补码的形式存储,正数的补码和原码一样,负数的补码由除符号位的原码(改数的绝对值)的反码加一得到
左移两位 -3 << 2
| 下标 | 符号位 | 3 | 2 | 1 | 0 | ||
|---|---|---|---|---|---|---|---|
| 位数 | 1 | 1 | 1 | 0 | 1 |
高位舍弃,低位补 0 ,结果为 -12 (结果仍为补码)
| 下标 | 符号位 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|
| 位数 | 1 | 0 | 1 | 0 | 0 |
右移 (>>) 和无符号右移 (>>>)
右移在移动后高位补符号位,低位舍弃,因此在右移负数时,得到的结果差别很大
无符号右移则为移动后高位补 0 ,低位舍弃(此时符号位会参与位移)