负数转换二进制
例:在带符号整数signed char的情况下,-57如何被表示成负数呢?在计算机中又是如何计算66-57呢?
解析
考虑int占有32位太长,因此使用只占8位的signed char类型来举例。57用二进制表示位00111001(补足8位)。如何表示一个负数?可以使用最高位的一位来表示正负,0表示非负,1表示负数。
第一种方式是用除了第一位的数字表示这个负数的绝对值,第一位变成1。这样,-57表示为10111001.这种表示方式称为原码,不过计算机不使用这种方式表示负数。
第二种方式是将这个负数的绝对值的数全部取反,由1变为0,0变为1。这样,-57表示为11000110.这种表示方式称为反码。使用反码有一个问题:0有两种表示方式(全0和全1)。所以也不常用。
第三种方式是先计算这个负数的反码,然后加1,这样,-57表示为11000111.这是计算机使用的表示负数的方法,被称为补码。这种表示方式下,0只有1个,全1代表-1.
有了补码这种表示负数的方式,计算机就可以很方便地计算二进制减法了。例如要计算66-57时,可以认为是66+(-57)。66的二进制是01000010,-57的二进制是11000111,列竖式累加(其实就是异或运算,记得进位)。
由于这个数字溢出了8位,所以只取低位数的8位,得到的答案是00001001,也就是十进制下的9.
补码这种精妙的设计使得计算机可以化减为加。但是谈论到补码时必须要确定总位数。
小数转换二进制
例:3.14转换成二进制是多少呢?
解析
将实数从十进制转换为二进制,可以将整数部分和实数部分分别处理。整数部分的3是十进制的11,而小数部分的0.14处理方式如下:
将原来的小数数字,每次都乘2,如果得到的结果中整数部分是1,则答案记录一个1,并去掉这个整数部分,然后继续计算;如果得到的结果中的整数部分还是0,那么答案记录一个0,继续计算。
因此3.14表示为二进制数是11.001000011……,在二进制下是一个无限小数。因此,这就是为什么计算机浮点数类型无法精确表示很多实数的原因。
那么,如果将一个二进制小数转换为十进制呢?例如101.101,同样将整数部分和小数部分分开,整数部分十进制是5,小数部分的计算方式和整数转换方式差不多:。所以整个数的十进制就是5.625.