基础知识
计算机中存储是用补码!!,同时注意一下计算省略了高位不变部分和 字节大小端问题
基础数据
- byte:有符号,在网络传输中都是会用到byte的,它占1个字节,共8位,比如说11111111就可以用1个
byte表示,转化为10进制:- (2的6次+2的5次+2的4次+2的3次+2的2次+2的1次+2的0次) = -127。
其中前7位表示数字,最高位表示符号,0为正,1为负。范围是 (-2的7次 ~ 2的7次 - 1),那为什么前
面最小是-127,范围最小又是-128呢?因为规定-0(10000000)为-128。 - short:有符号,占2个字节,共16位。同byte一样,它的取值范围就是 (-2的15次 ~ 2的15次 - 1)。
- int:有符号,占4个字节,共32位。它的取值范围就是(-2的31次 ~ 2的31次)。
- long:有符号,占8个字节,共64位,它的取值范围就是(-2的63次 ~ 2的63次)。
位运算
- ^:表示异或位运算,两者相同则为0,两者不同则为1。比如说15^2,15用二进制表示就是1111,2用2
进制表示就是0010,两者进行异或运算,结果就是1101,转换为十进制就是13。
A | B | A^B |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
- |:表示或运算,两者只有有一个为1就为1, 比如说13|2,13用二进制表示就是1101,2用二进制表示
就是0010,两者进行或运算,那么结果就是1111,转换为十进制就是15。
A | B | A | B |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
- &:表示与运算,两者都为1就为1,其余都为0,比如说15&2, 13用二进制表示就是1111,2用二进制
表示就是0010, 两者进行与运算,那么结果就是0010,转换为十进制就是2。
A | B | A&B |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
- ~:取反,就是本来是0变成1,本来是1变成0。
A | ~A |
---|---|
1 | 0 |
0 | 1 |
<<:左移运算符,不需要考虑符号位,因为在后面补0,把二进制的数字向左移动,低位补0。比如说 3<<2。
3的二进制码为11,向左移动2位就是1100,那么结果就是12。>>:右移运算符,带符号位。根据这个要移动的数字决定正负,如果是正数,那么就在前面补0,如果是
负数就在前面补1。比如说 3>>2,3的二进制码为00000011,向右移动2位,就变成00000000,转化为十
进制就是0了(3是正数所以在高位补0)。再比如说-3>>2,-3的二进制码为10000011,转化为补码
(只要涉及到负数,就需要转换到补码计算,正数之所以不用转化,是因为他们的补码和原码是一致的)
11111101,进行位移运算,就是11111111,这个是补码,需要再转回原码。那么就是取反+1,结果就是
10000001,转化为十进制就是-1。>>>:右移运算符,与上面的区别就是这个运算符是 无符号的。不论正负,高位都补0。如果要用
-3>>2来验证,因为高位补0,就需要把所有的位数都写全了。如果是int,那就要写成32位来运算。切记切记。
上面很多因为高位的变化“取反再取反”会导致前面所有的位都没变所以我就简化了,但是这个>>>运算符不行哦,
它会把负数变为正数。
栗子(eg):
比如说-15|3等于多少呢?有些人会觉得-15转化为二进制就是10001111,而3转化为二进制就是00000011,
那么结果应该是10001111呀,转换为十进制就是-15呀?大家可以自己写个demo就会发现是不对的。要注意
在计算机中所有的都是用补码的形式存储的,之所以上面介绍两个正数是对的,因为 正数的反码和补码都是一样的。而负数求补码应该是除去符号位取反+1,我们再来看看这个题-15|3,其中-15的原码为10001111,反码为11110000,那么补码就是11110001,然后3的补码为00000011,两者进行或操作就是11110011,你以为结束了么?还没有,再又要求它的原码了,原码就是补码再求补码再+1(是不是已经晕掉了?),也就是
10001101,结果就是-13。为了大家都好理解,我这里用算式整理一下:
求 -15|3
[-15]原码 = 10001111
[-15]反码 = 11110000 //原码求反码符号位不变
[-15]补码 = 11110001 //反码+1等于补码
[3]原码 = 00000011
[3]反码 = 00000011 //正数都一致
[3]补码 = 00000011 //正数都一致
-15|3 = 11110011 //两个补码进行或操作
[结果]补码 = 11110011 //上面求得的值
[结果]反码 = 10001100 //符号位不变
[结果]原码 = 10001101 //反码+1
100001101 转化为十进制就是-13。
不知道我这么解释会不会更加清楚一些呢?同理的,上面那些(尤其是求反‘~’我故意没写例子,大家自己去试试吧)。
在说一次,正数的原码,补码,反码都一样,如果一定要说为什么一样,我就举个例子。有这么一个等式7+(-7)=0。
我们知道
[-7]原 = 10000111
[-7]反 = 11111000
[-7]补 = 11111001
那么如果要存在一个值和[-7]补码相加等于0,是不是就是00000111!!所以正数的补码和原码是一致的。
这样解释虽然怪怪的,但是可以知道的确是这样的。
代码实现
基本步骤:
① 分析转化和代转化之间位数的关系
② 计算偏移量。每次都取最后8位
③ 把最后8位和0xff进行&操作
④ 得出结果。
有人会问,为什么要和0xff进行&操作?这里解释下,因为再分割的时候,我们要保证最后8位是一致的,更高位都要置0,这样才能保证数据的一致性。比如说由byte转化成short。位数从8位变成了16位,那么在计算机自己看来,它会把前面多出来的8位置1。而&0xff就可以把前面所有的位数都置0。
- short与byte的相互转化
1 |
|
- int与byte的相互转化
1 | public static byte[] int2byte(int s){ |
- long与byte的相互转化
1 | /** |
- char与byte的转化
1 | /** |
- float与byte的转化
1 | /** |
- double与byte的转化
1 | /** |
- boolean与byte的相互转化
1 | /** |
参考地址:
[1].long、shrot和int转化 https://blog.csdn.net/u012403290/article/details/68943827
[2].long、shrot和int转化 https://blog.csdn.net/thanklife/article/details/17002641
[3]. char、float、double与byte转化 https://blog.csdn.net/LEEtcWorks/article/details/7390731
[4]. 通过buffer转换 https://blog.csdn.net/u010983881/article/details/60870360