二进制运算
字节序
- 针对的是字节(byte) 本文讲的是二进制运算 ,两个不是一个概念,做了解即可
字节序分:大端字节序,小端字节序
大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
小端字节序:低位字节在前,高位字节在后,计算机处理这个更快。
网络字节序:使用大端字节序
TCP/IP协议 RFC1700规定使用“大端”字节序为网络字节序,其他不使用大端的计算机要注意了,发送数据的时候必须要将自己的主机字节序转换为网络字节序(即“大端”字节序),接收到的数据再转换为自己的主机字节序。这样就与CPU、操作系统无关了,实现了网络通信的标准化。 —— https://zhuanlan.zhihu.com/p/21388517
补码、反码、原码
- 原码:用第一位表示符号(0正数,1负数),其余位表示值。(原码是容易被人脑所理解的表达方式)
- 反码:正数的补码反码是其本身,负数的反码是符号位保持不变,其余位取反 (历史的产物,为了表达补码和原码的关系不得不存在)
- 补码:正数的补码是其本身,负数的补码是在其反码的基础上 + 1(计算机认这个)
总结一句话就是:正数的 原码 反码 补码 都一样,原码人更好理解,计算机只用补码,反码方便补码与原码之间的转换。
注意: 当前进制的最小负数无法表示为 反码,原码
二进制运算符
左移,算数右移,逻辑右移
位移操作根据当前进制进行操作,位移右面的值不能大于等于当前进制,在java中,当你指定位移的数大于等于限定的进制时,相当于转了一个大圈,从头开始(有点类似我们使用的%运算)。以8bit举例,当你 >>|>>>|<< 8时,其实相当于啥也没干,负数也是这个原理,当你 >>|>>>|<< -1时 相当于 >>|>>>|<< 7
- 左移 << 高位移丢,低位补0
为啥没有算数和逻辑之分? 因为高位第一位是符号位,而左移整体向左移动。符号位都没了,所以算术和逻辑是一样的
- 算数右移 >> 高位根据符号位补,是1补1,是0补0,低位移丢
- 逻辑右移 >>>高位补0,低位移丢
// 使用技巧 (以8进制举例):格式(未运算之前的二进制补码 > 运算后的二进制补码=运算后的二进制反码=运算后的二进制原码)
// 位移当前进制 = 位移0
// 偶数<<当前进制-1 永远等于0 例如: 2 << 7 = (0000 0010 > 0000 0000=0000 0000=0000 0000)
// 奇数<<当前进制-1 永远等于当前bit能表达的最大负数 例如: 1 << 7 = (0000 0001 > 1000 0000=无法表示=无法表示)
// 正数>>当前进制-1 永远等于0 例如: 127>> 7 = (0111 1111 > 0000 0000=0000 0000=0000 0000)
// 负数>>当前进制-1 永远等于-1 例如:-128>> 7 = (1000 0000 > 1111 1111=1111 1110=1000 0001)
// 正数>>>当前进制-1 永远等于0 例如: 127>>>7 = (0111 1111 > 0000 0000=0000 0000=0000 0000)
// 负数>>>当前进制-1 永远等于1 例如:-128>>>7 = (1000 0000 > 0000 0001=0000 0001=0000 0001)
逻辑运算符
在计算机逻辑运算中,只有3种逻辑 & | ~ (与或非) 而其他逻辑比如说 非与 异或 非或,都是基于这三元老组成的 (计算机所有的计算都基于此,加减乘除,圆周率计算....)
在java中 异或被简化为一个符号表示: ^ 而其他逻辑则需要 调用者手动转换 例如 ~(1 & 2)~是一元运算符,其余都是二元运算符
- &(与) 两边都为1时为1,否则为0
- |(或) 两边有一个为1时为1,否则为0
- ~(非) 为0时为1,为1时为0
- ^(异或) 两边都相同时为0,否则为1
//使用技巧 (以8进制举例):格式(未运算之前的二进制补码 > 运算后的二进制补码=运算后的二进制反码=运算后的二进制原码) = 十进制结果
// 正数&进制-1 等于%进制,%更好理解 &更快处理 4 & 7 = (0000 0100 & 0000 0111 > 0000 0100=0000 0100=0000 0100) = 4
// 8 & 7 = (0000 1000 & 0000 0111 > 0000 0000=0000 0000=0000 0000) = 0
// 12 & 7 = (0000 1100 & 0000 0111 > 0000 0100=0000 0100=0000 0100) = 4
// -1&任何数 等于任何数本身 -1 & 7 = (1111 1111 & 0000 0111 > 0000 0111=0000 0111=0000 0111) = 7
// -1 & 8 = (1111 1111 & 0000 1000 > 0000 1000=0000 1000=0000 1000) = 8
// 两个数^再^其中一个数会得到另一个数 4 ^ 3 = (0000 0100 ^ 0000 0011 > 0000 0111=0000 0111=0000 0111) 7
// 7 ^ 4 = (0000 0111 ^ 0000 0100 > 0000 0011=0000 0011=0000 0011) 3