在java中补零的作用是什么_浅谈Java中的补零扩展和补符号位扩展

今天,魏屌出了一道题,题目如下:

定义一个大头序的byte[]a={-1,-2,-3,-4},转换成short[]b.问b[0]和b[1]分别是多少?

乍一看,这题不难,无非就是移位操作,再进行组合。但是呢?对于用Java的童鞋来说,这里面有一个坑,稍不注意可能就踩进去了。在说之前,我先把代码和答案贴出来吧。

20180110231645972006.png

20180110231645973959.png

看到这里,可能有的童鞋比较奇怪,为啥要&0xff,这不相当于没变化吗?非也,不信我举个例子。

20180110231645975912.png

答案是-127和129。很奇怪不是吗?我想的明明都是-127啊!!!

解答这个问题之前,我们先注意一下,b1的类型是int,而不是byte,这是因为byte的任何计算操作之后,都默认转成int,先明确这个概念。

然后,重头戏来了,大学计算机组成原理我们都学过原码,反码和补码,概念问题这里就不说了,也不用想书本上那些定义,学以致用嘛,一张图说明问题。

20180110231645976889.png

是不是很easy?这里再强调一个问题,就是Java中只有有符号数!Java中只有有符号数!Java中只有有符号数!重要的事情说三遍!

那么好了,Java中的数值存储就像这个大圆盘!

我们接着看为什么输出129?已知byte经过计算之后会变成int,但是人家int是32位的啊,byte才8位,所以只能补位啦,诶呀,问题来啦,怎么补位呢?这也是今天想强调的哦!

b是byte类型,其计算机存储的补码是10000001(8位)。

转成int后,Java中的扩展方式是补符号位扩展,何谓补符号位扩展?就是变成了11111111 11111111 11111111 10000001(32位),为啥要这样变?因为这样变还是-127,数值大小没有变!

而我们如果&0xff呢? b&0xff=11111111 11111111 11111111 10000001&11111111=00000000 00000000 00000000 10000001,这个值就是129,这就是补零扩展啦!所以129的问题解决啦!

什么?你问补零扩展有什么用?我们回到魏屌的那道题,两个byte合成一个short,short可是16位哦,如果我们不&0xff,即写成

s[1] = (short)((bs[2] << 8) | bs[3]);

输出结果发现变成了-4。为什么呢?

还是刚才那个思路啊,bs[2]是-3,即11111101,bs[3]是-4,即11111100,

(bs[2] << 8)就变成了11111111 11111111 11111101 00000000,

((bs[2] << 8) | bs[3])就变成了11111111 11111111 11111101 00000000 | 11111111 11111111 11111111 11111100 = 11111111 11111111 11111111 11111100,

再转成short,就是11111111 11111100,结果就是-4啦!就酱紫!

所以Java中byte和short互相转换的代码应该是:

//short转byte

short x = -32752;//定义一个short

byte high = (byte) (0xFF & (x>>8));//定义第一个byte

byte low = (byte) (0xFF & x);//定义第二个byte

System.out.println(high);//打印第一个byte值

System.out.println(low);//打印第二个byte值//byte转short

short z = (short)(((high & 0xFF) << 8) | (0xFF &low));

System.out.println(z);//输出的结果就是-32752

最后总结一下:

因为Java中只有有符号数,当byte扩展到short, int时,即正数都一样,因为符号位是0,所以无论如何都是补零扩展;但负数补零扩展和按符号位扩展结果完全不同。

补符号数,原数值不变。

补零时,相当于把有符号数看成无符号数,比如-127 = 0x81,看成无符号数就是129, 256 + (- 127)。

对于有符号数,从小扩展大时,需要用&0xff这样方式来确保是按补零扩展。

而从大向小处理,符号位自动无效,所以不用处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值