计算机中的二进制

#一、概述
      计算机中的任何数据都是二进制,而编程语言是人与计算机之间的桥梁,编译语言利用算法,解决人类使用十进制与二进制之间的鸿沟。(官方一点)
      最近需要做一个解析二进制文件的功能,所以迫不得已,又得把大学早已忘记的知识给学回来。(大学老湿说,现在学不懂的也没关系,到社会上还会逼着你再学一遍。。果然很有道理)。废话不多说,正文开始。。。
#二、浅谈二进制
      由于也是刚刚开始学习,所以记录的东西也不是很深入,后续接触的多了,还会再补充。
      在我们的项目里,需要对二进制文件进行解析。由于整个文件内容较为复杂,这里只举个简单的小例子。
假设传进来的二进制数组为[-90,10,0,0],需要对此byte数组解析,代码参见

public static int byteToInt(byte[] bb) {
        if (bb.length == 1) {
            return (int) bb[0];
        } else if (bb.length == 2) {
            return (int) (((bb[1] & 0xff) << 8) | ((bb[0] & 0xff) << 0));
        } else if (bb.length == 4) {
            return (int) ((((bb[3] & 0xff) << 24) | ((bb[2] & 0xff) << 16) | ((bb[1] & 0xff) << 8) | ((bb[0] & 0xff) << 0)));
        }
        return -1;
    }

将此byte数组转换为int数值。
1.首先,要明白负整数在计算机中是以补码的形式存在,也可以说,计算机储存有符号的整数时,是用该整数的补码进行储存的。

注意:
1)原码,反码,补码是针对有符号的类型而言。
2)实数始终是有符号类型的,整型数据包括有符号和无符号的。

2.原码、补码与反码的概念及计算
1)原码:一个整数,按照绝对值大小转换成的二进制数,称为原码。
比如: 00000000 00000000 00000000 00000111 是7的 原码,10000000 00000000 00000000 00000111 是-7的 原码
正数的原码和补码、反码相同,负数的原码按照绝对值大小转换成的二进制数,然后最高位补1。

2)反码:正数的反码与原码相同,负数的反码出符号位各位取反。
取反操作指:原为1,得0;原为0,得1。(1变0; 0变1)
比如: 00000000 00000000 00000000 00000111的反码还是00000000 00000000 00000000 00000111,而10000000 00000000 00000000 00000111的反码为11111111 11111111 11111111 11111000

3)补码:正数的补码与源码相同,负数的补码为反码+1
比如: 00000000 00000000 00000000 00000111的补码就是00000000 00000000 00000000 00000111,而10000000 00000000 00000000 00000111的补码为11111111 11111111 11111111 11111001
由于负数在计算机中是以补码的形式存在,所以-7在计算机中的表示为:11111111 11111111 11111111 11111001。

3.代码解析
观察上面的代码片,会发现一个有趣的问题,就是每个byte之后要&一个0xff,这是为啥呢?
Java总是把byte当做有符处理,可以通过将其和oxFF进行二进制“与”得到他的无符号值。
byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。其实是从数字类型扩展到较宽的类型时,补零扩展还是补符号位扩展。
这是因为Java中只有有符号数,当byte扩展到short, int时,即正数都一样,因为为符号位是0,所以无论如何都是补零扩展;但负数补零扩展和按符号位扩展结果完全不同。
补符号数,原数值不变。
补零时,相当于把有符号数看成无符号数,比如-127 = 0x81,看成无符号数就是129, 256 + (- 127)
对于有符号数,从小扩展大时,需要用&0xff这样方式来确保是按补零扩展。
而从大向小处理,符号位自动无效,所以不用处理。

-90的补码为:‭11111111111111111111111110100110‬&0xff=‭11111111111111111111111110100110‬&11111111=00000000000000000000000010100110
10的补码为:
00000000000000000000000000001010
0的补码还是0,四个或操作
00000000 00000000 00000000 10100110
00000000 00000000 00001010 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
——————————————————
00000000 00000000 00001010 10100110=2726(DEC)

你可能感兴趣的:(java)