机器数
一个数在计算机中的表现形式叫做机器数,通常是二进制形式。
对于人脑来说,正负数的辨别、运算比较简单,比如-5+3=-2。但是对于计算机来说,加减乘除是最基本的运算,要设计的尽量简单,计算机辨别数的正负并进行运算会让计算机的设计电路变得很复杂,于是人们想出了让符号位也参与到运算上来。
用一个数的最高位(符号位)用来表示它的正负,其中0表示正数,1表示负数,其他位不变,我们称之为原码。
例如正数7,在计算机中用一个8位的二进制数来表示,是00000111,而负数-7,则用10000111表示,这里的00000111和10000111是机器数
真数
计算机中的机器数对应的真实的值就是真数,以日常生活中的十进制表示,比如上面的00000111和10000111来说,对最高位后面的二进制数转换成10进制是7,在结合最高位的值,得出对应的真数分别是7和-7。
原码
用第一位表示符号,其余位表示值。因为第一位是符号位,所以8位二进制数的取值范围就是:[1111_1111 , 0111_1111] 即 [-127 , 127] ,原码是容易被人脑所理解的表达方式。范围:-127~127
使用原码参数运算的缺陷
从上面的原码表中可以看见左边每增加一个二进制单位对应的真数是递减的,而右边每增加一个二进制单位对应的真数是递增的,所以对于原码来说,能满足正数的加法,但无法满足负数的加法
2+1 = [0000_0010]原+[0000_0001]原=[0000_0011]原 = 3
1+-1=[0000_00001]原+[1000_0001]原=[1000_0010]原=-2
反码
为了满足负数对加法的需求,就必须让负数与他对应的二进制码是同步递增或者同步递减,并且保证正负数的相加等于零。
于是就通过符号位不变,其余位取反来满足这个同步递增或者递减的要求,由于正数本来就满足它本身的加法,所以不需要做任何改变。这就是反码的定义由来。
正数的反码是其本身,负数的反码是符号位保持不变,其余位取反。例如正数1的原码是[0000_0001],它的反码是其本身[0000_0001],-1的原码是[1000_0001],其反码是[1111_1110]。
范围:-127~127
从上图的反码表中可以看到在运算不跨过0的时候,正负数的加法已经能满足要求
-2+1=[1111_1101]反+[0000_0001]反=[1111_1110]反=-1
但是这里有个不合理的地方,就是[1111_1111]和[0000_0000]都表示0,这导致在实际计算中每当跨过0一次,就有一个单位的误差,比如
-1+2=[1111_1110]反+[0000_0010]反=[0000_0000]反=0
补码
要解决这个问题必须把多余的-0给踢掉,规定只有0000_0000才表示0,重新排列负数使之正负数相加为0,也就是在反码的基础上加1。
正数的补码是其本身,负数的补码是在其反码的基础上+1,例如正数1的原码是[0000_0001],他的补码是其本身[0000_0001],-1的补码是[1111_1111]。
范围:-128~127
从上面的图中发现还有一个[1000_0000]的二进制没有对应任何真数,于是就规定了这个数的真数是-128
所以补码的表示范围是[-128~127] ,这样一来256个二进制正好表示256个整数。