我似乎记得每一次看到补码,都要花费一些时间来进行推敲,受够了。每一次都搞一次太他妈费劲了。这一次就写下来吧,希望对大家对自己都能加深理解。
一开始接触到补码的时候,老师讲的并不是很到位,知识大致的讲了怎么来进行计算,然而哪有什么卵用呢。
了物理底层对于计算的实现,可以将高低电压来分别表示0和1。
① 0:00 + 9hours = 9:00
②0:00 + 21hours = 9:00
③0:00 - 3 hours = 9:00
可以知道在时钟运算中,9,21,-3他们都是相等的,因为时钟是一个无限循环的轨道(找不到一个合适的词)。可以发现在余数是正数的时候,9,21,-3他们对12进行取余的结果都是9,这些数在数学上就叫做相等模。
方法来说明一下,三位无符号能表示的范围就是0~7,长度是8,所以他的模就是8。
① 1 + 2 = 3
② 5 + 6 = 101 + 110 = 1 011= 3(这里有溢出,只能保留住后面三位)
在②中真实的答案是11,但是在三位无符号的表示中,11和3对于机器来说都是一样的,他们对8来进行取余之后都是3,他们是8的相等模。在这里我们可以把他想成是一个长度为8的圆,如下图:
负数,但是时钟算法依然是能够成立的。依然是以三位数为例,三位带符号位的表示范围为(-4~3)。如下图,无符号和有符号之间的对应,可以看到无符号数和对应的有符号
数都是8的相等模。
我们拿几个例子计算一下:
① -1 + -2 = ?
原码计算的话: 101 + 110 = 1 011(3)很显然是不正确的。
利用上表表示的值计算的话:111 + 110 = 1 101,101查看上表得到的是-3,答案是正确的。读者还可以自己多测试几个,结果都是正确的哦。
一开始接触到补码的时候,老师讲的并不是很到位,知识大致的讲了怎么来进行计算,然而哪有什么卵用呢。
二进制
首先需要说说二进制。在我们平常生活中都是使用十进制来进行计算的,我想可能是因为人类有是个手指的缘故吧,方便数手指头,每一个手指头代表十进制中一个。但是在计算上是很难找到十个不同的状态来表示现实生活中的十进制的。二进制由18世纪德国数理哲学大师莱布尼兹发现的,我觉得发现这个真的很了不起。这就解决了物理底层对于计算的实现,可以将高低电压来分别表示0和1。
时钟算法
先来讲解一下这个时钟算法。现在要把时针从0点(12点)调到9点,可以有多种办法:① 0:00 + 9hours = 9:00
②0:00 + 21hours = 9:00
③0:00 - 3 hours = 9:00
可以知道在时钟运算中,9,21,-3他们都是相等的,因为时钟是一个无限循环的轨道(找不到一个合适的词)。可以发现在余数是正数的时候,9,21,-3他们对12进行取余的结果都是9,这些数在数学上就叫做相等模。
计算机里的时钟算法
计算机在不同情形下会分配不同长度的位数来存储数值,有8位,16位,32位,64位等。同样在计算中采取的也是时钟算法。我们这里采用三位无符号位表示的方法来说明一下,三位无符号能表示的范围就是0~7,长度是8,所以他的模就是8。
① 1 + 2 = 3
② 5 + 6 = 101 + 110 = 1 011= 3(这里有溢出,只能保留住后面三位)
在②中真实的答案是11,但是在三位无符号的表示中,11和3对于机器来说都是一样的,他们对8来进行取余之后都是3,他们是8的相等模。在这里我们可以把他想成是一个长度为8的圆,如下图:
![image](http://igoro.com/wordpress/wp-content/uploads/2010/08/image5.png)
从无符号到有符号
计算机避免不了要表达负数,于是牺牲数值表示位数的第一位来表示这个数的符号,如果是0,代表的就是正数,如果是1,代表的就是负数。尽管有正数和负数,但是时钟算法依然是能够成立的。依然是以三位数为例,三位带符号位的表示范围为(-4~3)。如下图,无符号和有符号之间的对应,可以看到无符号数和对应的有符号
数都是8的相等模。
![image](http://igoro.com/wordpress/wp-content/uploads/2010/09/image6.png)
![image](http://igoro.com/wordpress/wp-content/uploads/2010/08/image7.png)
我们拿几个例子计算一下:
① -1 + -2 = ?
原码计算的话: 101 + 110 = 1 011(3)很显然是不正确的。
利用上表表示的值计算的话:111 + 110 = 1 101,101查看上表得到的是-3,答案是正确的。读者还可以自己多测试几个,结果都是正确的哦。
补码
其实补码在上面无形当中就已经介绍给大家了。在上表中Binary Value就是Signed Value一列的补码。这里说一下关于补码的计算,在学校和各种书本上大多都是直接告诉你怎么算。其实自己琢磨一下也就能够明白原理了。对于一个采取n为存储的原码( 负数,正数我就不说了,都是一样的),除了符号位对其进行取反。假设原先的原码的值为x,除了符号位取反之后的值应该是2^(n-1) + 2^(n-1) - x - 1 = 2^(n-1) - x -1。加1之后就是2^(n-1) - x,哇撒,刚好跟x就是相等模。