本文最后更新于 20 天前,其中的信息可能已经有所发展或是发生改变。
基本概念
单位概念
位(bit):计算机中最小的数字单位,是“二进制数字”(binary digit)的缩写,它只能取 0 或 1 两个值,因此bit被称作“二进制位”。
字节(byte):8 个bit组成 1 个字节(byte),通常也是计算机中最常见的数据大小单位,用于表示 8 个二进制位的数字或字符。
在计算机中,一个bit指的就是一个二进制位,即最小的数字单位。
二进制表示
例如:
- 在计算机中,7 被表示为 0000,0111。其中,每四位加入 , 便于区分位数。
具体地:
- 0000,0111 表示的二进制数字是 00000111。
- 其中,前四位 0000 表示十进制下的 0,后四位 0111 表示十进制下的 7。
- 0times2^7 0times2^6 0times2^5 0times2^4 0times2^3 1times2^2 1times2^1 1times2^0=7
- 该表示法将数字 7 以二进制形式表示,并在前面补上了 0,使其达到了 8 比特位(bits)的宽度,常常使用这种形式来表示计算机存储的二进制数。
按照上述过程,理论上一个字节(8个bit位)最大表示的数值范围为:
- 0000,0000(0) sim 1111,1111(255)。
原码、反码、补码、移码
由于现实计算中不仅存在正数,还存在负数,因此按照上节中将一个字节中所有位都用来表示数是不合理的。
因此,在一些语言中区分了有符号数和无符号数,像上节中表示的是无符号数的表示方法。
原码表示法
在使用原码表示法时,二进制数的最高位表示符号位,0 表示正数,1 表示负数。
以使用 8 位二进制原码为例,表示 -7 的二进制原码的步骤如下:
- 将 7 的二进制表示转换为 8 位二进制数的原码: 0000,0111。
- 将该二进制数的符号位取反,即将第一位由“0”变为“1”,得到:1000,0111。
因此,在 8 位二进制原码表示法中,-7 的二进制原码为 1000,0111。
按照上述过程,在原码表示下,理论上一个字节(8个bit位)最大表示的数值范围为:
- 11111,1111(-127) sim 0111,1111(127)。
需要注意,这种方式的缺点是正数和负数的加减法需要额外处理符号位,较为复杂。
例如计算:-1 1 = 1000,0001 0000,0001 = 1000,0010(-2)
怎么会是呢???显然是不对滴,因此我们又引入了反码。
反码表示法
反码是一种用于计算机中表示负数的二进制数表示法。在反码中:
- 正数的反码与其原码相同;
- 而负数则取其对应正数的原码每一位取反(0变为1,1变为0)得到。
- 反码最高位仍作为符号位,0表示正数,1表示负数。
以使用 8 位二进制原码为例,表示 -7 的二进制反码的步骤如下:
- 将 7 的二进制表示转换为 8 位二进制数的原码: 0000,0111。
- 将该二进制数的每一位取反,即将所有的位由“0”变为“1”,得到:1111,1000。
因此,在 8 位二进制反码表示法中,-7 的二进制反码为 1111,1000。
现在计算:-1 1 = 1111,1110 0000,0001 = 1111,1111(反码)
注意:反码直接计算的结果需要取反才能得到原码,因此对 1111,1111 的非符号位全部取反得到 1000,0000(-0)。
显然是对的吧,数值是对了,但是出现了“ 0”和“-0”的问题,依然不合理,因此我们最终引入了补码。
补码表示法
补码是一种计算机中表示有符号整数的二进制数表示法,也是一种将负数转化为正数的方法。在补码中:
- 正数的补码与其原码相同;
- 而负数则为其二进制反码加一。
以使用 8 位二进制原码为例,表示 -7 的二进制反码的步骤如下:
- 将 7 的二进制表示转换为 8 位二进制数的原码: 0000,0111。
- 将每一位取反得到反码:1111,1000,然后末位 1 得到:1111,1001。
因此,在 8 位二进制反码表示法中,-7 的二进制补码为 1111,1001,由于 -6 的二进制补码为 1111,1010,故我们将原本为 1111,1000 表示为最小值 -8。
按照上述过程,在补码表示下,理论上一个字节(8个bit位)最大表示的数值范围为:
- 1000,0000(-128) sim 0111,1111(127)
现在计算:-1 1 = 1111,1111 0000,0001 = 1,0000,0000,其中多出来的一位 1 由于超过了补码的表示范围,故造成了溢出,最终的计算结果为 0000,0000(0)。
由此,我们通过补码可以将两个数的减法运算变为加法运算,但是由于符号位的存在,补码很难直接判断真值大小,因此引入移码的概念。
移码表示法
移码是一种为了方便计算二进制浮点数而设计的表示方法:
- 将每个真值加上一个偏置值,再进行存储;
举例:
例如 x 的真值为 10100:
x = 10100,[ x ]_移 = 2^5 10100 = 1,10100(用,分割符号位)
-x = -10100,[ -x ]_移 = 2^5-10100 = 0,01100
当 x = 0 时:
注意:
- 移码与补码只差一个符号位,符号位取反两者就能相互转换。
证明:
- 正数:[ x ]_ 移 = 2^n x,相当于在第 n 位 1,即在符号位取反。
- 负数:
,也相当于符号位取反。
IEEE 754 标准
根据国际标准 IEEE 754,任意一个二进制浮点数 V 可以表示成下面的形式: V = (-1)^S times M times 2^E
- (-1)^S 表示符号位,当 S=0,V 为正数;当 S=1,V 为负数。
- M 表示有效数字,大于等于 1,小于 2,但整数部分的 1 不变,因此可以省略。(例如尾数为 1111010,那么 M 实际上就是1.111010,尾数首位必须是 1,1 后面紧跟小数点,如果出现 0001111 这样的情况,去掉前面的 0,移动 1 到首位,随着时间的发展,IEEE 754标准默认第一位为 1,故为了能够存放更多数据,就舍去了第一位,比如保存 1.0101 的时候, 只保存 0101,这样能够多存储一位数据)
- 2^E 表示指数位。(用于移动小数点,所以说才称为浮点型)
比如, 对于十进制的 5.25 对应的二进制为:101.01,相当于:1.0101 times 2^2。所以,S 为 0,M 为 1.0101,E 为 2。因此,对于浮点类型,最大值和最小值不仅取决于符号和尾数,还有它的阶码,所以浮点类型的大致取值范围:
- 单精度:±3.40282347 times 10^{38}
- 双精度:±1.79769313486231570 times 10^{308}