书写数字的常用方法是十进制。例如:2157的千位是2,百位是1,十位是5,个位是7,这意味着可以将2157看作如下形式:
2×1000+ 1×100 + 5×10 + 7×1
也就是如下形式:
2×103+1×102+ 5×101+7×100
姑且认为,十进制得以发展的原因是我们都有10根手指。在某种意义上说,计算机的位只有2根手指,原因是它只能被设为0或1。因此,以2为基数的系统适用于计算机。它用2的幂代替10的幂。以2为基数表示的数字称为二进制数。数字2对于二进制数的作用和数字10对于十进制数的作用是相同的。例如,二进制数1101可表示为一下形式:
1×23+ 1×22 + 0×21+ 1×20
以十进制数形式表示为:
1×8+ 1×4 + 0×2 + 1×1 = 13
可以使用二进制系统将任何整数表示为1和0的组合。这种系统非常适于数字计算机使用,数字计算机使用打开和关闭状态的组合来表示信息,而这些状态可以使用1和0表示。
二进制整数
这里128是2的7次幂,依此类推。该字节可以保存的最大数是把所有的位都设置为1:11111111。该二进制数的值如下:
128 + 64 +32 + 16 + 8 + 4 + 2 + 1 = 255
最小的二进制数是 00000000,或一个简单的0。一个字节可以存储的范围是0到255,总共256个可能的值。通过改变对位模式的解释方式,一个字节可以存储从-128到+127之间的整数,总共还是256个值。
有符号整数
1 – 1 = 1 +(-1) = 00000001 + 10000001 = 10000010 = -2
这个结果显然是不正确的。为了解决这个问题,我们引入了反码:
1 – 1 = 1 +(-1) = 00000001 + 10000001 = 00000001 + 11111110 = 11111111 = 10000000 = -0
发现结果的真值部分是正确的,而符合位存在问题,虽然人们理解上+0和-0是一样的,但是0带符号是没有意义的。因此,补码的出现就是解决这个问题:
1 – 1 = 1 +(-1) = 00000001 + 10000001 = 00000001 + 11111111 = 100000000
结果为9位,去掉最高位,结果为00000000 = 0。这样0用00000000表示,可以用10000000表示-128。
补码再深入
二进制浮点数
5 ÷10+ 2 ÷100 + 7÷1000
其中的分母是10的依次递增的幂。在二进制小数中,使用2的幂作为分母,因此二进制小数 .101 代表:
1÷2+ 0÷4 + 1÷8 = 0.50 + 0.00 +0.125 = 0.625
像1/3这样的许多小数不能用十进制计算法精确地表示。同样,许多小数也不能用二进制计数法精确地表示。实际上,二进制计数法只能精确地表示多个1/2的幂的和。因此3/4和7/8可以精确表示为二进制小数,但是1/3和2/5却不能。
要在计算机中表示一个浮点数,需要留出若干位(其位数取决于系统)存放一个二进制小数,其他位存放一个指数。总之,数字的实际值是二进制小数部分乘以2的指定次幂。比如用4乘以一个浮点数,则指数增加了2,二进制小数不改变。用一个不是2的幂的数乘以一个浮点数,则会改变二进制小数,如果有必要也会改变指数部分。
本文参考了C Primer Plus, Fifth Editon Chapter 15. Bit Fiddling