# 计算机二进制运算与实际应用
# 正整数转二进制,负整数转二进制,小数转二进制
在说明换算之前,先介绍一下次方和负次方的概念:
^ 在这里为幂等 不是位运算符的异或
| 2^2 = 2×2 = 4 |
| 2^-2 = 1÷2^2 = 1÷4 = 0.25; |
# 1,正整数转二进制
在计算机中存储字节是定长的,即我们 8、16、32 位等等,6 的二进制位为 110,但如果在 8 位计算机中是 00000110,高位补零
# 2,负整数转二进制
取反就是把 1 变 0,加 1 就是把最右边的 1 挪到后面一位去
| |
| 00000110 |
| 11111001 |
| 11111010 |
# 3,小数转二进制
小数转二进制,先把整数为转换成二进制,然后把小数位转换 (小数为换算每次乘 2,不足 1 为 0),最后相加,6.25 的二进制为 110.01
| 6.25 |
| 6 = 110 |
| 0.25×2 = 0.5 |
| 0.5×2 = 1 |
| |
# 二进制转换正负整数以及小数
# 1,二进制转正整数
二进制位左边首位为 0 为正数(6 —>00000110),1 为负数 (-6---->11111010)
| 00000110 |
| .....2^2,2^1,2^0 |
| 2^0 × 0 = 0; |
| 2^1 × 1 = 2; |
| 2^2 × 1 = 4; |
| ... |
| |
# 2,二进制转负整数
-6 的二进制位为 11111010, 取反为 00000101,然后加 1 为 00000110,110 为 6,故值为 - 6
| 11111010 取反为00000101,然后加1为00000110,110为6 然后再转负 |
# 3,二进制转小数
和小数转二进制一致,先算整数位,再算小数位,最后相加
| 0.01 |
| 2^0 2^-1 2^-2 |
| 2^0 * 0 = 0; |
| 2^-1 * 0 = 0; |
| 2^-2 * 1 = 1 ÷ 2^2 = 1 ÷ 4 = 0.25; |
| 0+0+0.25 = 0.25 |
# 原码,反码,补码
建议阅读该文章:原码 反码 补码 概念 原理 详解
- 计算机操作的都是补码
- 正数的原码,反码,补码一样
- 负数的反码,符号位不变 (第一位),其它位反过来,补码,在反码基础上加一
X=+101011 , [X]原= 0010_1011 ,[X]反=0010_1011,[X]补=0010_1011
X=-101011 , [X]原= 1010_1011 ,[X]反=1101_0100,[X]补=1101_0101
# 位运算符
# & (位与)
| |
| 1&1=1 , 1&0=0 , 0&1=0 , 0&0=0 |
| 0000 0011 |
| 0000 0101 |
| 0000 0001 |
| |
| 1.一个数 & 一个数 = 最小值为0,最大值为这两个中最小数 |
| 2.一个大于1的数 & 这个数-1 = 如果等于 0 则这个数肯定是2的幂等(因为只有2的幂等数转换为2进制只有一个1) |
| |
| |
| if(0 == (a & 1)) { |
| |
| } |
| |
| int[] a = new int[6]; |
| int 51; |
| 51 & a.lenght-1 = 1 |
| a[1] = 51; |
| |
| |
| a > 1 && (a & (a-1)) == 0 |
# | (位或)
| |
| 1|0 = 1 , 1|1 = 1 , 0|1 = 1 , 0|0 = 0 |
| 0000 0011 |
| 0000 0101 |
| 0000 0111 |
| |
| 1.一个数 & 一个数 = 最小值为这两个中最大数,最大值为这个两个数之和 |
# ^ (异或)
| |
| 1^0 = 1 , 1^1 = 0 , 0^1 = 1 , 0^0 = 0 |
| 0000 0011 |
| 0000 0101 |
| 0000 0110 |
| |
| 根据运算规则 1^0 = 1 , 1^1 = 0 , 0^1 = 1 可看出构成一个闭环。二进制后数据就这个样子所以可以得出结论 |
| 1.知道任意两个数可以异或出另一个数,且这三个数任意两数异或都是剩下的数 |
| 2.一个数 ^ 相同数 = 0 |
| 3.一个数 ^ 0 = 这个数 |
| |
| a ^= b; |
| b ^= a; |
| a ^= b; |
# ~ (取反)
| |
| 1 = 0; 0 = 1; |
| 0000 0101; |
| 1111 1010; |
| ~5 = -6 |
| |
| 1.将二进制0与1弄反,不是反码首位也会改动 |
| 2.~一个数 = 这个数的反数+1 |
| |
| a > 0 ? a : ~a+1; |
# <<(左移)
| |
| 5<<2 |
| 0000 0101 |
| 0001 0100 |
| -5>>2 |
| 1111 1011 |
| 11(左移丢弃) 1110 1100 |
| |
| 1.移动时最左边第一个数永远不变 |
| 2.移动时尾数补0 |
| 3.向左移就是×2的n次幂,移动n次就是2的n次幂 |
# >> (右移)
| |
| 5>>2 |
| 0000 0101 |
| 0000 0001 01(丢弃) |
| -5>>2 |
| 1111 1011 |
| 1111 1110 11(丢弃) |
| |
| 1.移动时正数左边第一位补0,负数补1 |
| 2.向右移就是÷2的n次幂,移动n次就是2的n次幂 |
| 3.负数每次移动如果有余数会加上余数,最小值为-1,正数最小值为0 |
# >>> (无符号右移)
| |
| 5>>>2 |
| 1111 1011 |
| 0011 1110 11(丢弃) |
# 组合使用
# 1. 生成第一个大于 a 的满足 2^n 的数
| public int tableSizeFor(int cap) { |
| int n = cap - 1; |
| n |= n >>> 1; |
| n |= n >>> 2; |
| n |= n >>> 4; |
| n |= n >>> 8; |
| n |= n >>> 16; |
| return (n < 0) ? 1 : (n >= 1 << 30) ? 1 << 30 : n + 1; |
| } |
# 2. 求绝对值 (比较是右移)
| |
| a >> 31 == 0 ? a : (~a + 1); |
# 3. 计算二进制中 1 的个数
| count = 0 |
| while(a){ |
| a = a & (a - 1); |
| count++; |
| } |
# 4. 判断是否为 2. 的幂等
| a > 1 && (a & (a - 1)) == 0 |
# 5. 将整数 A 转换为 B, 需要改变多少 bit 位
| |
| a ^= b; |
| count = 0 |
| while(a){ |
| a = a & (a - 1); |
| count++; |
| } |
| count |
# 总结
待续~~