`
shake863
  • 浏览: 661203 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

为什么要用补码来做存储

 
阅读更多


看了些补码的知识,摘抄了些,自己整理了些。

顺便带着两个小问题:

INT_MAX = 2147483647 ;

cout<<INT_MAX+1<<endl; //正确结果为-2147483648

UINT_MAX = 4294967295;

cout<<UINT_MAX+1<<endl; //正确结果为0

开始正文:

负数在计算机中如何表示?

举例来说,+8在计算机中表示为二进制的1000,那么-8怎么表示呢?

很容易想到,可以将一个二进制位(bit)专门规定为符号位,它等于0时就表示正数,等于1时就表示负数。比如,在8位机中,规定每个字节的最高位为符号位。那么,+8就是00001000,而-8则是10001000。

但是,随便找一本《计算机原理》,都会告诉你,实际上,计算机内部采用2的补码(Two's Complement)表示负数。

什么是2的补码?

它是一种数值的转换方法,要分二步完成:

第一步,每一个二进制位都取相反值,0变成1,1变成0。比如,00001000的相反值就是11110111。

第二步,将上一步得到的值加1。11110111就变成11111000。

所以,00001000的2的补码就是11111000。也就是说,-8在计算机(8位机)中就是用11111000表示。

不知道你怎么看,反正我觉得很奇怪,为什么要采用这么麻烦的方式表示负数,更直觉的方式难道不好吗?

为什么要用2的补码

首先,要明确一点。计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。

2的补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。

还是以-8作为例子。

假定有两种表示方法。一种是直觉表示法,即10001000;另一种是2的补码表示法,即11111000。请问哪一种表示法在加法运算中更方便?

随便写一个计算式,16 + (-8) = ?

16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:

 00010000
+10001000
---------
 10011000

可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电路。

现在,再来看2的补码表示法。

 00010000
+11111000
---------
100001000

可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。

2的补码的本质及正确性

我们要看先一下模的概念

“模”是指一个计量系统的计数范围。如时钟等。计算机也可以看成一个计量机器,它也有一个计量范

  围,即都存在一个“模”。例如:

  时钟的计量范围是0~11,模=12。

  表示n位的计算机计量范围是0~2^(n)-1,模=2^(n)。

  “模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的

  余数。任何有模的计量器,均可化减法为加法运算。

  例如: 假设当前时针指向10点,而准确时间是6点,调整时间可有以下两种拨法:

  你可以往回拨4个小时,也可以向前拨8个小时(12-10+6,在钟表系统里模是12)

  在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。

  对“模”而言,8和4互为补数。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特

  性。共同的特点是两者相加等于模。

  对于计算机,其概念和方法完全一样。n位计算机,设n=8, 所能表示的最大数是11111111,若再

  加1称为100000000(9位),但因只有8位,最高位1自然丢失。又回了00000000,所以8位二进制系统的

  模为2^8。 在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以

  了。

       再次重申一下这句话:

      在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。      

      所以对于模为10000 0000的8位系统来说,减去b和加上10000 0000-b是一个道理,而(10000 0000-b)是什么?恰好就是b的补码

补码怎么求,“取反加一”这口诀怎么来的?

承认了8 - 5 = 8 + (-5的补码)这个事实后,我们来看-5的补码怎么求,“取反加一”怎么来的

其实看完了上面的模的问题,该问题的答案基本已经出来了

-5的补码是 10000 0000 - 5 = 1111 1111 + 1 -5 = (1111 1111 - 5) + 1

1111 1111减去一个数事实上就是在对这个数取反,后面那个是+1

两个小问题的解释:

(1)

32位系统里,int的最大值为01111111 11111111 11111111 11111111,加1之后为

10000000   00000000   00000000   00000000。这个数是什么?

首先这是个负数-->负数在计算器里都是补码形式存放-->这是个补码-->那么真值是?--> -2147483648(已知负数的补码求该负数,不会求的百度一下吧。。。)

(2)

对于unsigned,最大值(32个1)加1后最前面的1自然丢失,剩下32个0,所以就是0。

结束。


分享到:
评论
1 楼 damoqiongqiu 2013-04-15  
非常好的文章,很透彻

不过有一句话小僧腆着脸补充一下:

“1111 1111减去一个数事实上就是在对这个数取反”

这句话的原理如下:

+5的原码为0000 1010,反码为1111 0101
-5的原码为1000 1010,反码为1111 0101 (按位取反,符号位不变)

因此,绝对值相等的两个正负整数,补码是相同的

+5的反码又可以这样算:
1111 1111-0000 1010=1111 0101

故,用1111 1111减去一个正数,即为此正数(包括对应的负数)的反码

因此:
-5的补码=10000 0000 - 5 = 1111 1111 + 1 -5 = (1111 1111 - 5) + 1
成立

即,负数的补码等于其反码+1

相关推荐

    为什么需要反码和补码?.docx

    转换补码为原码的过程对于负数来说稍微复杂一些。负数的补码被视为负数的原码,然后对这个补码再次求补,即符号位不变,其余各位取反并加1。这将恢复负数的原始二进制表示。 总之,原码、反码和补码是计算机中表示...

    二进制补码、小数的补码及运算规则

    补码是一种常见的概念,在计算机系统中,数值一律用补码来表示(存储)。补码的主要特点是:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。补码的表示方法是在原码的基础上进行修改,原码...

    Java为什么使用补码进行计算的原因分析

    首先,让我们理解什么是原码、反码和补码。原码就是直接表示数值的二进制形式,包括一个符号位,0表示正数,1表示负数。对于正数来说,原码、反码和补码都相同;但对于负数,反码是原码除符号位外的所有位取反,而...

    补码源码反码转换工具,补码反码原码的转换工具,C/C++

    在计算机系统中,通常使用补码来存储和处理有符号整数。 4. **MFC(Microsoft Foundation Classes)**: MFC是微软提供的一个C++类库,它提供了对Windows API的封装,使得开发者能够更容易地构建Windows应用程序。...

    计算机组成原理补码计算

    在C++中,我们可以用int、short、long等有符号整型变量来存储带符号的数字,这些变量在内存中是以补码形式存储的。例如,对于一个8位的二进制数,若最高位为0,则表示正数,如0000 0001表示+1;若最高位为1,则表示...

    补码工具.rar

    补码是一种在计算机科学中表示有符号整数的方法,它对于理解计算机内部如何存储和处理数值至关重要。在汇编语言编程和编译器设计中,理解补码的概念和操作是必不可少的知识点。VB6(Visual Basic 6)是微软开发的一...

    计算机基础知识:原码反码补码练习(含答案)

    这是因为对于负数,将补码转换为十进制需要先取反(除符号位外),然后加1,即10110100取反为01001011,加1得到01001010,这是-76的原码,转换为十进制就是-76。 6. 二进制正数的补码与其原码相同,因为它们不需要...

    二进制补码加法器实验1

    总结来说,这个实验是计算机组成原理教学中的一个重要实践环节,它使学生能够亲手搭建和操作补码加法器,从而直观地理解二进制补码运算的机制,为理解和掌握计算机内部的算术运算打下坚实基础。同时,实验也锻炼了...

    原码和补码 基础教程

    - **简化减法运算**:利用补码可以将减法转换为加法运算,从而简化了硬件实现。 - **统一正0和负0**:正0和负0在补码中的表示均为`00000000`。 **3. 示例** - -3的补码计算过程如下:`[10000011]补 = 11111101`。 -...

    原码、反码、补码

    - 负数-5的原码为`10000000000000000000000000000101`,反码为`11111111111111111111111111111010`,补码为`11111111111111111111111111111010 + 1 = 11111111111111111111111111111011`。 #### 五、示例解析 **例...

    二进制补码一位乘法规律的推导

    其中,补码在加减法的运算中具有许多优势,因此在计算机系统中,数值一般用补码来表示(存储)。 补码乘法的递推公式较复杂,需要从补码与真值的关系出发,推导出补码的右移公式,并最终给出二进制补码一位乘法规律...

    计算机中的补码是什么?.docx

    那么,为什么要有补码?补码的优点是什么?补码的出现是为了解决符号数表示的问题。符号数可以分为正数和负数两种,而原码和反码都无法处理负数的问题。补码的出现解决了这个问题,使得计算机可以正确地表示和处理...

    原码反码补码讲课.pptx

    原码反码补码讲课 计算机中的数值表示是计算机基础知识的重要组成部分。在计算机中,数值可以分为整数和实数两大类。整数又可以分为无符号整数和带符号整数。无符号整数是指不带符号的整数,而带符号整数则是带有...

    原码、反码、补码三码转换(C#)

    在计算机科学中,原码、反码和...在实际应用中,理解原码、反码和补码的概念对于理解计算机底层数据存储和处理非常重要,尤其是在进行位运算和溢出检查时。通过C#等编程语言进行实践,能更好地帮助我们掌握这些概念。

    补码的乘法,除法算法演示,以及浮点数的内码输出代码

    在计算机科学中,补码是表示有符号整数的一种方式,它被广泛应用于现代计算机的存储和计算。补码系统不仅用于整数运算,还涉及到浮点数的处理。本项目将通过具体的操作演示补码乘法、除法算法,并提供浮点数内码的...

    定点补码一位乘法器的设计

    这样做的好处是可以用同样的操作处理加法和减法,比如在二进制加法器中,两个数相加时,如果结果超过最大值(溢出),则相当于进行了减法运算。 在定点补码一位乘法器的设计中,我们需要考虑如何处理正数和负数的...

    MM.rar_补码_补码转换

    1. 定义一个变量,存储输入的补码值。 2. 检查最高位(符号位),如果为1,则执行负数的转换过程。 3. 对补码值(不包括符号位)执行位取反操作。 4. 对结果加1,得到负数的原码。 5. 如果最高位为0,那么这个数就是...

    原码、反码、补码的相关原理

    在现代计算机体系结构中,数值一般采用补码形式存储和运算,这是因为补码不仅简化了加减法的运算流程,而且使得符号位可以与数值位一样参与运算,无需额外的硬件支持。在高级编程语言中,虽然程序员通常不直接接触到...

    四位补码加法和减法器(含有设置溢出位和进位)

    本例中的代码就是用Verilog语言实现了一个四位的补码加减法器。 #### 知识点三:四位补码加减法器 本模块实现了一个四位的补码加减法器,其中包含了一位符号位和三位数值位。具体来说: - 输入端口包括: - A[3:...

    计算机中的原码、反码和补码

    在深入探讨计算机中表示有符号整数的原码、反码和补码之前,让我们先回顾一下计算机存储数据的基本单位——字节。正如文中所述,一个字节由8位组成,每位可以是0或1,因此一个字节可以表示\(2^8 = 256\)种不同的状态...

Global site tag (gtag.js) - Google Analytics