计算机中的原码,反码,补码的理解总结

目录

概念:

原码:

反码:

补码:


概念:

简述:

Everybody Kown,计算机历史上有两位很重要的人物,第一位是计算机科学奠基人(Alan Mathison Turing) 阿伦·图灵 ,他在计算机科学方面的贡献主要有两个,一是建立图灵机(Turing Machine,TM)模型,奠定了可计算理论的基础;二是提出了图灵测试(Turing Test),阐述了机器智能的概念……(计算机里面最高的奖项就是图灵奖,每年颁发给在计算机科学领域做出杰出贡献的人才,被誉为计算机业界和学术界的诺贝尔奖),

第二位则是被称为现代计算机之父的美籍匈牙利数学家(Von Neumann) 冯·诺依曼,他的主要贡献是1945年,冯·诺依曼在指定EDVAC(电子离散变量计算机)的计划中(公认的第一台计算机),提出了存储程序的概念,就是将程序和数据一起存放在存储器中,以后凡是以此概念为基础的各类计算机,都被称为冯·诺依曼计算机,它的特点主要包括了:

  1. 计算机有运算器,存储器,控制器和输入设备,输出设备五大部件组成
  2. 指令和数据以同等地位存于存储器中,并可按地址寻访
  3. 指定和数据均用二进制代码表示
  4. 指令由操作码和地址码组成,操作码用来表示操作的性质,地址码用来表示操作数在存储器中的位置
  5. 指令在存储器内按顺序存放,通常,指令是顺序执行的,在特定的条件下,可以根运算结果或根据设定的条件改变执行顺序
  6. 机器以运算器为中心,输入输出设备与存储器键的数据传送通过运算器完成。

其中运算器,只有加法运算器,没有减法运算器

  1. 减法和加法是一样的,只要加个电信号,把减数变成负的就可以了,把加变成减,看看加法器的电路图,一般“加法器”同时是“减法器”。
  2. 乘法器和除法器:乘法器很简单,用加法器多加几次,或者增加硬件,多弄几个加法器就可以了,乘数、被乘数都要先转化为二进制,二进制的乘法远比十进制简单,比如乘数是1011,只需将将被乘数分别左移3位、1位,移动后补入0,并将这三个数(被乘数左移3位的、被乘数左移1位的及未移位的被乘数)在累加器中相加,所得总和就是积,根据需要积可再转化为十进制。
    除法与乘法类似,除法就是乘法的逆运算,只不过将左移改为右移,加改成减。实际上减也是通过取补码后再加,因此计算机芯片上的累加器是最繁忙的部分。运算比较复杂,大概就是这么回事。
  3. 乘法运算使用加法和移位操作实现的,根据机器数的不同,又分为原码乘法和补码乘法,具体的细节记不太得了……就不一一赘述了。(这个是涉及到位运算,一般在开发中很少使用位运算的,具体怎么运算的是computer的cpu完成的,复杂且繁琐,如果特别感兴趣,《计算机组成原理》中有详细的介绍……)
  4. 除法运算可用加(减)和移位操作实现的,根据机器数的不同,又分为原码除法和补码除法,具体的细节记不太得了……就不一一赘述了。(这个是涉及到位运算,一般在开发中很少使用位运算的,具体怎么运算的是computer的cpu完成的,复杂且繁琐,如果特别感兴趣,《计算机组成原理》中有详细的介绍……)

 

  1. Notice:计算机硬件结构中,也不全是“只有一个加法器”,至少还有“浮点运算的加法单元和浮点乘法,浮点除法的单元”.

       所以,计算机中没法直接做减法运算的,它的减法运算都是通过加法运算来实现的

比如,10 - 3 = 7 ,这很简单,在计算机中,它会加上减数的相反数得到的是一样的结果: 那么就是 10 + -3 = 7;所以这时候就要有负数的概念,那么这就是为什么不得不引入一个符号位来表示正数,和负数了,(最高位是符号位,“0” 表示正数,“1”表示负数)

说明: 原反补码的引入是为了做负数的运算的,整数的原反补码都是一样的!


原码:

原码就是指的二进制定点表示法,每个十进制数字都有它对应的二进制码,即最高位是符号位,“0” 表示正数,“1”表示负数,其他的位数存放该数的二进制的绝对值,也就是表示该数值的大小。

如下图所示,给出部分数字的二进制原码;

 

比如:

先加正数(这很简单):

3 + 3 = 6 ;换成二进制就是:(这没问题)

  3       +      3    = 6

0000 0011 + 0000 0011 = 0000 0110 

0 + 0 = -0;换成二进制就是:(这也没问题,0 和 -0 本身就是同一个数字)

    0     +     -0     = -0

0000 0000 + 1000 0000 = 1000 0000

但如果是一个正数加它的相反数:比如:

3 + -3 = ? ; 换成二进制就是:

   3      +    -3     = -6 

0000 0011 + 1000 0011 = 1000 0110 

3 + -3 = -6? why?

原因很简单: 就是表示正负数的符号位所引起的

不光只是一个正数加它的相反数使用原码运算会这样,负数和负数使用原码运算也是会出现莫名其妙的效果的;

比如:

  -3      +     -3    = 6 

1000 0011 + 1000 0011 = 1(丢弃最高位1) 0000 0110 (由于一个字节规定了只能是八个位所以最高位丢弃不要,硬件决定了)

由此可以看出,如果是正数之间的运算使用原码进行运算,完全没有任何的问题,因为这本身就是一个很简单的二进制加法,但是正数和负数,负数和负数的运算就有问题了;

于是,引入了反码:
 

 


反码:

正数的反码与原码相同而负数的反码,是对其原码逐位取反,符号位不变(所谓取反就是 1 变 0 , 0 变 1)

如下图所示,给出部分负数数字的二进制反码;

光是从原码的运算就不难看出,原码最大的问题就在于任意一个正数加上它的相反数不等于 0 ;

紧接着: 试试用正数的原码加上它的相反数的反码?

比如:

3 + -3 = ?

  3       +   -3(反码) = -0(就是0本身)
0000 0011 + 1111 1100  = 1111 1111

3 + -3 = 0;

 

正数 + 负数?

 7(原码) + -2(反码) = -5(反码)
0000 0111 + 1111 0010  = 1111 0101

再比如:

 -4(原码)+ -4(反码)= 6(原码)?
1000 1011 + 1111 1011 = 1(丢弃最高位)0000 0110 (由于一个字节规定了只能是八个位所以最高位丢弃不要,硬件决定了)

负数相加?why?

-1(原码) + -5(反码)= -7(反码)?
1000 0001 + 1111 1010 = 1111 1000 

发现明显不对:

反码的出现的好处就是解决了正数加它的相反数等于0  和正数加负数的运算的结果是正确,而负数和负数相加的结果始终都是错的,这始终不是还不是完美的解决方案;

于是引入了补码:


补码:

正数的补码与其原码相同(换言之就是正数的原、反、补都是一样的);负数的补码是在反码的末位 + 1;(负数的补码是它的原码自低位向高位,尾数的第一个  “1” 及其右边的 “0” 保持不变,左边的各位按位取反,符号位不变,0除外!0则全部取反,0比较特殊,介于正数与负数之间,它的原、反、补都是 0000 0000 ,它严格意义上来说属于自然数!)

 

如图所示:

补的概念:

例如生活中的时钟:

比如现在是6点整,那么下一次到3点整的时候会在多少个小时呢?

  1. 逆时针3小时之前 即 6h - 3h = 3h
  2. 顺时针9小时之后 即 6h + 9h = 15h , 15h - 12h = 3h

可见 -3 可用 +9 代替 减法 ———》 加法

称 +9 是 -3 以 12为模的补数 , 可以说 6-3 和 6+9 在模为12的情况下的结果是等效的

记作 -3 \equiv +9 \left (mod 12 \right )

同理 -4\equiv +8 \left (mod 12 \right )

        -5 \equiv +7 \left (mod 12 \right )

现在再来试验

正数与负数相加,

比如:

  3(补码)+  -6(补码)= -3 (补码)    
0000 0011 + 1111 1010 = 1111 1101

 

 -2(补码)+  7(补码) = 5(补码) 
1111 1110 + 0000 0111 = 1(丢弃最高位1)0000 0101(由于一个字节规定了只能是八个位所以最高位丢弃不要,硬件决定了)

正数与它的相反数相加

 9(补码) +  -9(补码)= 0(补码)
0000 1001 + 1111 0111 = 1(丢弃最高位1) 0000 0000(由于一个字节规定了只能是八个位所以最高位丢弃不要,硬件决定了)
 6(补码) + -6(补码) = 0(补码)
0000 0110 + 1111 1010 = 1(丢弃最高位1)0000 0000(由于一个字节规定了只能是八个位所以最高位丢弃不要,硬件决定了)
  0(补码)+  -0(补码) = 0(补码)
0000 0000 + 0000 0000 = 0000 0000

Notice:从数学的角度来说 0 和 -0 就是同一个数, 0这个数比较特别,介于正数和负数之间,它的绝对值就是它本身,它并没有相反数,它就是自然数中的一类!

 

负数与负数相加:

  -4(补码)+ -5(补码) = -9(补码)
1111 1100 + 1111 1011 = 1111 0111 
 -2(补码)+ -6(补码) = -8(补码) 
1111 1110 + 1111 1010 = 1111 1000
-8(补码) + -9(补码) = -17(补码)
1111 1000 + 1111 0111 = 1110 1111
-7(补码)  + -3(补码) = -10(补码)
1111 1001 + 1111 1101 = 1111 0110

OK,Perfect ,运算全部正确!

 

Notice:如果运算结果超出了其字节大小所表示的范围,会产生不正确的结果:比如:这里使用的是八个字节, -60 + -70 = 126 ,产生了数值溢出!

 -60(补码)+  -70(补码)= 126(补码)?   
1100 0100 + 1011 1010 = 1 0111 1110

此时就要选择2个字节来表示运算结果了,正确结果如下:

 -60(补码)         + -70(补码)         = -130(补码)
1111 1111 1100 0100 + 1111 1111 1011 1010 = 1111 1111 0111 1110

 

由此可见!计算机中的运算都是按照补码的形式进行运算的!

 

平时使用的计算器,它的负数都是已经以补码的形式转好了的,

由于正数的原码,反码,补码都是一样的,所以看到的始终都是一样的二进制码!

不难看出,计算机科学家们引入了原码、反码、补码的就是为了解决做减法的问题,加减乘除四则运算甚至更复杂的运算得到很完美的解决方案!存在即合理,尤其是这种发明的,定死的,千万不要纠结为什么要有反码?,为什么要有补码?我猜之所以这样,设计理念,设计思想均来源于生活,只能说二级制和十进制的运算机制不一样……,它没有加减乘除法口诀表…… 加法,减法是相对的,乘法,除法是相对的……,就好比正数, 负数是相对的一样

 

简单整理了一下,谢观……

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值