二进制详解

机器数

一个数在计算机中的二进制表现形式,叫做这个数的机器数.机器数是带符号的,在计算机用一个数的最高位存放符号,正数位为0,负数为1.

例:+3(10) ------ 0000 0011(2) 计算机字长8位

真值

带符号的机器数对应的真正数值称为机器数的真值.

例:1000 0011(2) ------该数据代表的真值为-3(10).

源码、反码、补码

数值在计算机中是以补码的方式存储的, 我们首先了解下原码, 反码和补码的概念,然后再看下为什么要使用补码。
一个数, 计算机要用一定的编码方式进行存储。 原码, 反码, 补码就是计算机存储数字的编码方式。

  • 原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
  • 反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
  • 补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)

计算机为什么要使用补码呢?

首先,根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1+(-1), 所以计算机被设计成只有加法而没有减法, 而让计算机辨别”符号位”会让计算机的基础电路设计变得十分复杂,于是就让符号位也参与运算,从而产生了反码。
  用反码计算, 出现了”0”这个特殊的数值, 0带符号是没有任何意义的。 而且会有[0000 0000]和[1000 0000]两个编码表示0。于是设计了补码, 负数的补码就是反码+1,正数的补码就是正数本身,从而解决了0的符号以及两个编码的问题: 用[0000 0000]表示0,用[1000 0000]表示-128。
   注意-128实际上是使用以前的-0的补码来表示的, 所以-128并没有原码和反码。使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数。 这就是为什么8位二进制, 使用补码表示的范围为[-128, 127]。

-12补码推导

负数的补码是除最高位之外取反+1
十进制的-12转换成二进制为1000 1100(最高位代表符号、负数为1,正数为0;后7位表示数值),最终补码为1111 0100,然后byte --> int 由8位变 32 位,由于是负数,所以高24位全部补1: 1111 1111 1111 1111 1111 1111 1111 0100 ;

0xFF 是计算机十六进制的表示: 0x就是代表十六进制,A B C D E F 分别代表10 11 12 13 14 15 F就是15 一个F 代表4位二进制:可以看做 是 8 4 2 1。0xFF的二进制表示就是:1111 1111。 因为是正数所以高24位补0:0000 0000 0000 0000 0000 0000 1111 1111;

-12的补码与0xFF 进行与(&)操作 最后就是0000 0000 0000 0000 0000 0000 1111 0100
转换为十进制就是 244。

byte类型的数字要&0xff再赋值给int类型,其本质原因就是想保持二进制补码的一致性。

当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。

Java中只有有符号数,当从小扩展到大

一、正数,因为为符号位是0,所以无论如何都是补零扩展

二、负数补零扩展和按符号位扩展结果完全不同
1.补符号数,原数值不变。
int类型 11111111 11111111 11111111 10000001(补码) -127
byte类型 10000001(补码) -127

2.有符号数补零扩展,数值为无符号数
从小扩展大**时,需要用&0xff这样方式来确保是按补零扩展。
1111111111111111111111111 10000001&11111111=000000000000000000000000 10000001 ,
这个值算一下就是129,相当于把有符号数看成无符号数, 256 + (- 127)=129
从大向小处理,符号位自动无效,所以不用处理。

read()方法返回值为什么是int

read()方法读取的是一个字节,为什么返回是int,而不是byte
因为字节输入流可以操作任意类型的文件
比如图片音频等,这些文件底层都是以二进制形式的存储的
如果每次读取都返回byte
有可能在读到中间的时候遇到111111111
那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了
后面的数据就读不到了
所以在读取的时候用int类型接收
如果11111111会在其前面补上24个0凑足4个字节
那么byte类型的-1就变成int类型的255了
这样可以保证整个数据读完,而结束标记的-1就是int类型

1字节的表示范围为-128到127,为什么不是-128到128

在计算机中一般来说,一个字节8位,即可表示 2^8=256,有符号数那就是-128到128了,但实际表示的范围是-128到127。

在补码中用(-128)代替了(-0),所以补码的表示范围为: (-1280127)共256个.

-1-127的结果应该是-128,在用补码运算的结果中, [1000 0000]补 就是-128。但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示。(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制,使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]。

十进制转二进制

二进制详解

二进制转十进制

把每个数位单独转换后把所有的转换结果求和

例:01001110 = 2^6 + 2^6 + 2^2 + 2^1 = 64 + 8 + 4 + 2 = 78