为什么 您所在的位置:网站首页 为啥1k是一千 为什么

为什么

2023-03-15 04:31| 来源: 网络整理| 查看: 265

刚好遇到这个问题,我想我应该能让你明白。先说明,前面我会说一堆,然后在最后回答你的问题。

计算机中存储数字都是用二进制,假设现在有一个四位的二进制存储器,它的每一位都有“强”和“弱”两个状态,分别表示1和0,这4位二进制让你存数字,能存什么范围的数呢?

二进制存数字,本质上就是把每个二进制编码对应一个十进制数,4位二进制能有几种编码呢(就是有几种排列组合方式)?由于每位有0和1两种值,一共4位,所以它能表示的编码数为:2x2x2x2(每位都有0和1两种值,4位,就是4个2相乘),其实就是2的4次方=16种编码,这16种编码如下(箭头右边表示它们对应的十进制数):

0000 --> 0 0001 --> 1 0010 --> 2 0011 --> 3 0100 --> 4 0101 --> 5 0110 --> 6 0111 --> 7 1000 --> 8 1001 --> 9 1010 --> 10 1011 --> 11 1100 --> 12 1101 --> 13 1110 --> 14 1111 --> 15

也就是说,它们分别表示0到15一共16个数(注意是从0开始数,所以数到15的时候已经是16个数了)。

但是你现在提到了负数,所以我们现在换成用4位二进制来表示有符号的整数,怎么表示符号呢?聪明的前辈们发现,上面的16个数中,前面8位和后面8位,除了最高位不同,其它都完全相同,于是他们想到了用“最高位”表示符号,最高位为0表示正数,最高位为1表示负数,所以上边的数字写成有符号的就是:

0~7的二进制 0000 --> 0 0001 --> 1 0010 --> 2 0011 --> 3 0100 --> 4 0101 --> 5 0110 --> 6 0111 --> 7 -0~-7的二进制(把0~7的最高位,即最左侧那位改为1,则是负数) 1000 --> -0 1001 --> -1 1010 --> -2 1011 --> -3 1100 --> -4 1101 --> -5 1110 --> -6 1111 --> -7

好,现在问题来了,+1 ~ +7,-1 ~ -7 这十四个数没什么好说的,但关键在于,现在有一个“+0”和一个“-0”(1000这个编码中,最高位1是符号位,表示负数,后面三个都是0,所以是“-0”,这个应该不难理解吧?)。

我们知道,无论是正0还是负0,它都是0啊,0可没有正负之分,那怎么办?难道“0000”和“1000”这两个编码,你要放弃其中一个不用?

答案是:当然是不可能放弃它!

事实上二进制数字存储系统跟时钟一样,都是一个有“模”的概念。“模”就是计量范围!比如时钟的计量范围是0-11,共12个数,所以时钟的“模”就是12。“模”既是起点,也是终点,比如时钟的模是12,12既是起点,也是终点,到了终点又重新再来一遍,起点和终点是“一个重合的值”。

同理,对于只能存4位二进制的存储器来说,它的计量范围是0-15,总共能存下16个数,所以它的“模”就是16,16也是0,为什么呢?因为4位二进制能存的最大数是1111,这个二进制数转成十进制是15,15+1=16,由于15的二进制就是1111,我们试试把1111加1会变成多少?

1111 0001 ------ 10000

发现没,二进制1111+1=10000,这已经是5位了,由于我们的前提是存储器只能存4位,那么其实第5位是存不下的,就是所谓的“溢出”了,溢出了就是丢弃了。而10000这个数正是2的4次方,也就是16,所以它虽然是16,但由于多出的一位已经丢弃了,所以它本质上就是0,所以为什么说“模”是终点也是起点,就相当于时钟,转到12点之后,12点也是0点,它既是起点也是终点,这两个点是重合在一起的。

其实无论是无符号的正数,还是有符号的正负数,都是可以把它们分布在一个圆里,就像时钟一样。

假设有一个时钟有16个刻度,如下图所示,每一个数在圆里都是对称的,比如-1和7,-2和6他们的间隔都是8(模),而-1和1,-2和2,它们的二进制是相互对应的,除了最高位,其它都一样

现在关键的问题这个“-0”,即二进制1000到底应该表示什么值?事实上,在上图中,我们人为规定“-0”是十进制“-8”。为什么呢?原因有多个:

1、从上图中看,-7到-8,是一个很自然的事情;2、有人可能会说,为什么不规定它为“+8”?因为如果规定它为“+8”,那么正数部分就+0 ~ +8 共9个数,与负数部分就不对称了;3、前面两个都是表面的,真实原因是:像 (-0)+1 = 1、+7+(-0) = +7 这样的计算,如果你不把“-0”规定为“-8”,它就无法运算,或者说运算结果不对。

为了完成上面第3点的运算,我们先来看看前面说的16种4位0,1组合对应的补码是多少?

原码 补码 十进制 0000 0000 --> 0 0001 0001 --> 1 0010 0010 --> 2 0011 0011 --> 3 0100 0100 --> 4 0101 0101 --> 5 0110 0110 --> 6 0111 0111 --> 7 1000 1000 --> -0 1001 1111 --> -1 1010 1110 --> -2 1011 1101 --> -3 1100 1100 --> -4 1101 1011 --> -5 1110 1010 --> -6 1111 1001 --> -7

我们通过补码来计算一下:(-0)+1 = 1

1000 -- (-0补) 0001 -- (1补) ---- 1001 -- (?补) 补=反+1 反=补-1 反=1001(补) - 1 = 1000 原=1111 (该数第1位为符号位,表示负,后面3位表示十进制数7,合起来就是-7,并不是我们设想中的(-0)+1 = 1)

再通过补码计算一下:+7+(-0) = +7

0111 -- (+7补) 1000 -- (-0补) ----- 1111 -- (?补) 补=反+1 反=补-1 反=1111(补) - 1 = 1110 原=1001 -- 这个数是 -1,并不是我们设想中的+7+(-0) = +7

可以看到,上面两个运算结果都不是我们想像中的那样,都是不对的,这表明,只有把“-0”规定为“-8”时,这两个运算才是正确的,如果把它看成“-0”,那么它的运算结果是不对的,也就是说,不可能出现“(-0)+1 = 1”,“+7+(-0)=+7”这样的算法,必须是“-8+1=-7”,“+7+(-8)=-1”,如果真的要表示0+1=1,7+0=7,那么0要写成+0(当然正数一般不写+号,所以就是0),而不能是“-0”。

其实从另一个角度来看,那就是,所有有-0参加的加法运算,得到的结果,都必须把-0看成是-8,结果才是正确的,也就是说,按二进制的计算规则,-0只能解释为-8,才能让结果正确。

好了,现在要回答你的问题了

:为什么-8的原码是1000? :它本质上应该是“-0”,但因为0没有正负,已经有一个+0了,就没必要再有一个“-0”,所以人为规定“-0”为“-8”,这既是为了让正负数刚好对半分,也是为了让“-8+1=-7”,“+7+(-8)=-1”这些运算能得出正确结果;

:为什么-8的反码为1111? :反码就是原码除符号位外,按位取反,1000除了第1位是符号位,其它三位按位取反就变成111,再加上符号位,那不就是1111么?

:为什么-8的补码也是1000? :负数补码=反码+1,反码前面已经算出来了是1111,1111+1=10000,第5位1存不下,溢出了,其实就变成了0000,按这个算法,它的补码就应该是0000对吧?为什么实际上它的补码为1000呢?其实这里已经不能用反码+1来算了,因为这个数非常特殊,想要知道为什么-8的补码也是1000,需要往下看补码的原理!

到底什么是补码??

想要知道什么是补码,首先要知道补码为什么叫“补”码?它“补”的是什么??

其实,所谓补码,就是“补”上多少刚好“装满”,什么叫装满?“满”就是“模”。

我们简化点来说,用时钟来说吧,时钟有0-11点共12个刻度(虽然0的位置一般写成12,但它本质上是0),比如时间1和11互为补码,1和-1也互为补码,因为1+11=12(模),1+(-1)=0(模),模既是0也是12(它们是重合的)。

我们来看一下 -1 ~ -7 的补码是怎么计算的,就是“模 - 负数原码的绝对值”,绝对值其实就是把符号位去掉(或者说改为0)就行

原码 补码 十进制 0000 0000 --> 0 0001 0001 --> 1 0010 0010 --> 2 0011 0011 --> 3 0100 0100 --> 4 0101 0101 --> 5 0110 0110 --> 6 0111 0111 --> 7 1000 1000 --> -0 模 绝对值 补码 1001 1111 --> -1 => 10000 - 0001 = 1111 (1要补上15才等于16) 1010 1110 --> -2 => 10000 - 0010 = 1110 (2要补上14才等于16) 1011 1101 --> -3 => 10000 - 0011 = 1101 (3要补上13才等于16) 1100 1100 --> -4 => 10000 - 0100 = 1100 (4要补上12才等于16) 1101 1011 --> -5 => 10000 - 0101 = 1011 (5要补上11才等于16) 1110 1010 --> -6 => 10000 - 0110 = 1010 (6要补上10才等于16) 1111 1001 --> -7 => 10000 - 0111 = 1001 (7要补上9才等于16)

注意,上边计算负数的补码时,是不使用负号的,补码也是没有符号的,就像下图,我要算-4和-1之间相差多少,我只需要拿他们的绝对值4和1来计算:4-1=3即可知道它们相差3,而这个差值在上边的二进制里其实就是补码,所以补码虽然都是1形头,但这个1并不是符号位,而是二进制数字本身

按上边计算的负数的补码的规律,从-1到-7,补码依次减1,所以不难推测,-7后面的-8,它的补码就是1000。

而如果按“模-绝对值”这个算法,就有点问题了。如果按二进制码的方式,那么-8(或者说是-0)的二进制是1000,直接把1去掉就是绝对值,所以它的绝对值是0,那么10000-0=10000,而最左侧的1是第5位,是实际上是存不下的,所以实际结果就是0000,这么算的话,跟前面的理论就完全对不上了。

但是如果不从二进制来说,从十进制-8来说,它的绝对值是8,8要补上8才等于16,而8的二进制就是1000,所以-8的补码就是8(即二进制1000)。

还有一种思路,就是-0也是0,而0是没有正负的,所以它实际上不属于负数,不是负数,则补码等于原码,因为原码是1000,所以补码自然也就是1000了。

所以这个-0或者说-8,真的非常的特殊,只有你把它认为是-8时,它参与运算才是正确的,或者反过来说,所有-0参与的运算,-0都表现为-8,也就是说,只有把它解释为-8时,它所参与的运算才解释的通,所以推算-0的补码也是与普通负数不一样,可以根据我上面所说的思路,也可以认为它就是一个规定吧。规定对于n位存储器,如果存储的是有符号整数,-0就是 -2^{(n-1)} ,也是-2^{n} 的一半。

正数的补码:为什么正数的原码与补码相加,就不是等于模呢?因为在这个正负数系统中,正数的补码根本就不是它的补码,而是它自己,自己跟自己相加当然不可能等于模了,书本所谓的“正数的补码”只不过是为了统一概念,因为我们说,在计算机中,数的运算是以补码的形式运算的,所以为了统一,就规定正数的补码是它自己。事实上真正意义上的正数的补码并不是它自己,而是用模减去正数后,得到的数,比如模为8,那么1的补码就是7,而不是1,而实际上计算机中正数是没有用补码去运算的,它用的就是原码,所谓的“补码”,只不过是我们人为的把原码说成是补码而已。为什么这么说呢?因为正数压根不需要用到补码,补码的存在,是为了把减法变成加法。

补码存在的原因,是为了把减法变成加法,这样计算机只需要一套电路(或者说一套程序)即能完成加法和减法的运算,因为在最初最原始的计算机中,程序都是直接的电路,一个程序是非常庞大,需要很多电子元件,非常的贵,电子元件多也非常的耗电,所以与其为减法做一套单独的“减法运算电路”,还不如从数学方法上,把减法变成加法,这样减法运算也能直接用加法电路来做,这样可以节省很多电子元件,从而节点很多费用,而补码正是把减法变成加法的一个原理。现代的电脑虽然不是直接用电子元件做出一个程序,但cpu内部其实也是一套复杂的电路,只是我们看不见而已。

以上的原理可以扩展到任何2^n位二进制,比如8位二进制(一个字节),那么它能表示的是256个数,如果用它来保存有符号整数,那么正数部分是0~127,负数部分是-1 ~ -128,-128也是人为规定的(它实际上是“-0”)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有