您的位置:首页 > 职场人生

long、int和short与byte之间的转化

2017-04-01 13:56 155 查看

引言

昨天有个朋友问我long转byte要怎么转,然后吃饭期间我问了身边的人,发现也不会转。所以我想有必要写一些位操作符和转化规则,同时还有一些不常用,但是源码中经常出现的操作符。不可能所有的都写出来,但是举一反三就可以了。在技术点中介绍一些不常用但是常见的操作符,后半部分展示实现转化的代码。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290

技术点:

计算机中存储是用补码!!,同时注意一下计算省略了高位不变部分

1、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。

2、short:有符号,占2个字节,共16位。同byte一样,它的取值范围就是 (-2的15次 ~ 2的15次 - 1)。

3、int :有符号,占4个字节,共32位。它的取值范围就是(-2的31次 ~ 2的31次)。

4、long:有符号,占8个字节,共64位,它的取值范围就是(-2的63次 ~ 2的63次)。

5、^:表示异或位运算,两者相同则为0,两者不同则为1。比如说15^2,15用二进制表示就是1111,2用2进制表示就是0010,两者进行异或运算,结果就是1101,转换为十进制就是13。

ABA^B
110
101
011
000
6、|:表示或运算,两者只有有一个为1就为1, 比如说13|2,13用二进制表示就是1101,2用二进制表示就是0010,两者进行或运算,那么结果就是1111,转换为十进制就是15。

ABA或B
111
101
011
000
7、&:表示与运算,两者都为1就为1,其余都为0,比如说15&2, 13用二进制表示就是1111,2用二进制表示就是0010, 两者进行与运算,那么结果就是0010,转换为十进制就是2。

ABA&B
111
100
010
000
8、~:取反,就是本来是0变成1,本来是1变成0。

A~B
10
01
注意本来我打算不想解释这块的,但是学知识,既然要学了,就尽自己最大努力一次性一个知识点学透彻。我举个例子,比如说-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!!所以正数的补码和原码是一致的。这样解释虽然怪怪的,但是可以知道的确是这样的。

9、<<:左移运算符,不需要考虑符号位,因为在后面补0,把二进制的数字向左移动,低位补0。比如说 3<<2。3的二进制码为11,向左移动2位就是1100,那么结果就是12。

10、>>:右移运算符,带符号位。根据这个要移动的数字决定正负,如果是正数,那么就在前面补0,如果是负数就在前面补1。比如说 3>>2,3的二进制码为00000011,向右移动2位,就变成00000000,转化为十进制就是0了(3是正数所以在高位补0)。再比如说-3>>2,-3的二进制码为10000011,转化为补码(只要涉及到负数,就需要转换到补码计算,正数之所以不用转化,是因为他们的补码和原码是一致的)11111101,进行位移运算,就是11111111,这个是补码,需要再转回原码。那么就是取反+1,结果就是10000001,转化为十进制就是-1。

11、>>>:右移运算符,与上面的区别就是这个运算符是无符号的。不论正负,高位都补0。如果要用-3>>2来验证,因为高位补0,就需要把所有的位数都写全了。如果是int,那就要写成32位来运算。切记切记。上面很多因为高位的变化“取反再取反”会导致前面所有的位都没变所以我就简化了,但是这个>>>运算符不行哦,它会把负数变为正数。

代码实现

基本步骤:

①分析转化和代转化之间位数的关系

②计算偏移量。每次都取最后8位

③把最后8位和0xff进行&操作

④得出结果。

有人会问,为什么要和0xff进行&操作?这里我做一下解释,因为再在割的时候,我们要保证最后8位是一致的,更高位都要置0,这样才能保证数据的一致性。比如说由byte转化成short。位数从8位变成了16位,那么在计算机自己看来,它会把前面多出来的8位置1。而&0xff就可以把前面所有的位数都置0。

1、short 与 byte互相转化

public static byte[] short2byte(short s){
byte[] b = new byte[2];
for(int i = 0; i < 2; i++){
int offset = 16 - (i+1)*8; //因为byte占4个字节,所以要计算偏移量
b[i] = (byte)((s >> offset)&0xff); //把16位分为2个8位进行分别存储
}
return b;
}

public static short byte2short(byte[] b){
short l = 0;
for (int i = 0; i < 2; i++) {
l<<=8; //<<=和我们的 +=是一样的,意思就是 l = l << 8
l |= (b[i] & 0xff); //和上面也是一样的  l = l | (b[i]&0xff)
}
return l;
}


2、int和byte的转化也差不多

public static byte[] int2byte(int s){
byte[] b = new byte[2];
for(int i = 0; i < 4; i++){
int offset = 16 - (i+1)*8; //因为byte占4个字节,所以要计算偏移量
b[i] = (byte)((s >> offset)&0xff); //把32位分为4个8位进行分别存储
}
return b;
}

public static int byte2int(byte[] b){
int l = 0;
for (int i = 0; i < 4; i++) {
l<<=8; //<<=和我们的 +=是一样的,意思就是 l = l << 8
l |= (b[i] & 0xff); //和上面也是一样的  l = l | (b[i]&0xff)
}
return l;
}


那么long和byte的转化,甚至是long和short等之间的转化大家自己琢磨。看到这里是不是觉得自己要学的东西很多,大学学过的都忘记了呢?没关系,以后我会经常给大家复习一些重要但是不常用的东西哦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息