嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

周梦康 发表于 2015-10-09 13036 次浏览 标签 : 计算机基础

今天看到一段代码

private String byte2HexStr(byte[] b) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < b.length; i++) {
        String s = Integer.toHexString(b[i] & 0xFF);
        if (s.length() == 1) {
            sb.append("0");
        }
        sb.append(s.toUpperCase());
    }
    return sb.toString();
}

里面在获取一个整数的十六进制字符串的时候对byte类型的数字做了& 0xFF的操作,为什么要做这个与操作呢?

带着这个问题,所以有了这一篇博客。之前学习原码、反码、补码,都是学完了就还给老师了,在 PHP 里也机会没有用到过,今天在 Java 上检验出自己这块知识的不足。

查看了好多文章,似乎都有一点误导,给人的感觉就是,补码是由源码到反码,再转换成补码。(规则可部分参考: http://blog.csdn.net/pud_zha/article/details/7815109)如果根据那个规则,发现在8位的情况下,很难推导出-128的反码,因为8位的原码没法表示-128,这可难倒我了。最后发现了这篇文章:http://www.zhihu.com/question/20159860/answer/21113783 解开我的心结。下面自己小结下:

补码的原理:

引入模的概念,拿时钟举例子,12小时为模,假如当前时间为2点整,如果要把时间调整为6点整的话,我们可以选择向前拨4小时,也可以选择向后拨8小时,用一个伪表达式来表示

2 + 4 = 6
/** 这只是我根据上面的说法自定义的一种运算规则 **/
2 + (-8) = 6
/** 这个时候4和-8就是一个补数的关系,他们的模就是12 **/

补码存在的意义:

类似于上面的时钟的拨动问题,在计算机系统中,数值一律用补码来表示和存储。使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一为加的方式来处理。

补码的实际算法:

例如 byte 的取值范围为-128~127,实际其模是256,负数的补码等于用模减去数值的绝对值。(为什么模是256?因为 byte 为1字节8位,能表示的无符号数字,为0到255。)

回到-128的补码是多少这个问题?用这个补码算法来计算就是256-128=128(二进制就为10000000),如果说128比较特殊,那么计算下-127,-1的补码,都正确。所以从原码到补码的推导过程就是一个坑。


现在回到最开始我的那段代码的问题上,为什么要进行& 0xFF操作呢?

byte i = -1;
System.out.println(Integer.toHexString(i));//ffffffff
System.out.println(Integer.toHexString(i & 0xFF));//ff

为什么会出现上面的情况呢?因为 int 类型是4字节,32位,-1的补码就是

System.out.println(Integer.toBinaryString(-1));
//11111111111111111111111111111111

转成十六进制就是8个 f 了,而 i 在这里只是一个 byte 类型的数字,只有8位,如果直接转成 int 类型,前面的24位就都会补上1,所以这个时候,如果要取其十六进制字符串的时候,需要把前面的24位都消除,办法就是与0xff就行与操作

11111111111111111111111111111111
00000000000000000000000011111111
--------------------------------
00000000000000000000000011111111

这样就能确保 i 的十六进制字符串是8位的了。

嗨,老铁,欢迎来到我的博客!

如果觉得我的内容还不错的话,可以关注下我在 segmentfault.com 上的直播。我主要从事 PHP 和 Java 方面的开发,《深入 PHP 内核》作者之一。

[视频直播] PHP 进阶之路 - 亿级 pv 网站架构的技术细节与套路 直播中我将毫无保留的分享我这六年的全部工作经验和踩坑的故事,以及会穿插着一些面试中的 考点难点加分点

评论列表