- 浏览: 637437 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
sztime:
可以在文本框上绑定事件来禁用回车键, 我就是这样做的.在IE中 ...
form 回车自动提交问题 -
damoqiongqiu:
非常好的文章,很透彻不过有一句话小僧腆着脸补充一下:“1111 ...
为什么要用补码来做存储 -
wuyizhong:
原来如此啊。
form 回车自动提交问题 -
luliangy:
谢楼主~!
用C语言扩展Python的功能 -
kwong:
很有用,谢谢
火狐和IE 对css 样式解释的差异
为什么要用补码来做存储
- 博客分类:
- c/c++
看了些补码的知识,摘抄了些,自己整理了些。
顺便带着两个小问题:
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。
结束。
评论
不过有一句话小僧腆着脸补充一下:
“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
发表评论
-
strlcpy 的历史
2012-11-05 18:51 633strlcpy 并不属于 ANSI C,至今也还不是标准 ... -
c中的移位操作
2012-04-12 18:18 862位移位运算符是将数据看成二进制数,对其进行向左或向 ... -
google test 使用
2009-01-03 13:59 3504安装: 下载Google C++ Testi ... -
string 的 data() 和c_str()
2008-12-24 01:17 1155data 是字符数组,里面有 '\0 '当然也不会 ... -
C/C++ unit testing tools (18 found)
2008-12-19 01:27 1941C/C++ unit testing tools (18 f ... -
climits中的符号常量
2008-12-10 11:43 1115climits中的符号常量 符号常量 ... -
ICE初次
2008-09-02 01:48 1815按照某人的说法:跨平台的C++网络编程ICE才是王道。于是,我 ... -
对 pthread_cond_wait 的错误理解
2008-08-28 15:52 2059在线程的调度中经常会用到 pthread_cond_wait ... -
环形缓冲
2008-08-27 17:20 926/** * Copyright (c) 2008, ×××研 ... -
Linux下C语言编程的 RPC远程调用编程
2008-07-17 15:38 3372在查看libc6-dev软件包提供的工具(用 dpkg -L ... -
C++中重载操作符时什么时候定义成友元,什么时候定义为成员方法
2008-07-10 18:05 3501在C++语言中,可以用关键字operator加上运算符来表示函 ... -
c++中的存储类型
2008-07-06 00:46 1882存储类型是从变量的存 ... -
libevent 一个time server
2008-05-19 11:20 1266#include <netinet/in.h> # ... -
自己动手改写komodo sourcetree插件 对C/C++的支持
2008-04-16 22:11 1360其实很简单了, 找到sourcetree.js 的 ... -
GNU C的 __attribute__ 机制
2008-04-15 15:34 735GNU C 的一大特色(却不被初学者所知)就是 __attri ... -
module的认识和写法
2008-04-15 15:29 666不知道在什幺时候,Linux 出现了 module 这种东西, ... -
dynamic_cast、static_cast、const_cast 和 reinterp
2008-04-10 15:16 1348dynamic_cast、static_cast、co ... -
static_cast、dynamic_cast、reinterpret_cast、和const_c
2008-04-10 15:14 6195static_cast、dynamic_cast、reinte ... -
关于Linux下C/C++程序编译
2007-08-23 18:15 3634在编译之前我们需要 ... -
使用 setfill、setw 和 setprecision 基数的示例
2007-08-23 19:00 2692使用 setfill、setw 和 setprecision ...
相关推荐
详解原码、反码与补码存储与大小 原码: 如果机器字长为N个bit,那么一个数的原码就是N位二进制数,最高位 是符号位,1代表负数,0代表正数。 反码: 正数的反码就是原码,负数的反码就是符号位不变,其他取反。...
补码,在Java(以及大多数现代计算机系统中)中,整数通常使用补码(Two's Complement)形式来表示。补码表示法不仅简化了加减运算,还使得负数的存储和正数一样简单高效
64采样点的正弦表存储区。外接地址可以输出正弦信号采样点经过二进制补码转换后的幅度值。
反码是数值存储的一种,但是由于补码更能有效表现数字在计算机中的形式,所以多数计算机一般都不采用反码表示数。 在数值数据中分为有符号数与无符号数,其中,有符号数的最高位为符号位,最高位为“0”代表正数,...
引入补码是为了解决计算机中减法问题int型例子:浮点表示负指数问题:将指数表示位分成左右两份,中间为0,两边表正负数值,小于中间是负,大于中间是正d部分存储小数
字变量BUF1是以原码表示的有符号数,要求将其转换为反码和补码,分别存入BUF2和BUF3单元,并在屏幕上显示出来。 两个两字节无符号数分别放在存储单元A、B起始的缓冲器中,求其和,结果放在A起始的缓冲区并在屏幕上...
java实现源码转补码JavaScript Snowball Stemmers 所有 JavaScript 词干分析器都是从使用 transpiler 的词干算法的 Java 实现中转译而来的。 该项目不仅提供预构建的 JavaScript 词干分析器,还允许创建新的词干分析...
十进制转换二进制计算机是采用二进制存储的,计算机的二进制编码方式也分为原码,反码,补码方法。这是一个把十进制数字转换到它的二进制原码的算法,希望能给大家一些启发吧!这个算法我是用VB6写的,其中用到了...
本题分数:2 用8位补码表示有符号整数时,十进制整数-128的补码用十六进制表示是( ). A、FFH B、80H C、A0H D、7FH 学员答案:b 说明: 本题得分:2 题号:4??题型:单选题(请在以下几个选项中选择唯一正确答案)??本题...
汇编实验报告可以看看。有部分源代码和截图
计算机组成原理课设CISC模型源码,包含RAM+ROM模型
A Java 内部只有二进制补码 B Java 内部采用补码运算, 自动发送上溢出和下溢出 C Java内部没有10进制! 但是Java尽量按照人类习惯输入输出 D 补码的负数 最高位是 1, 也称作符号位
java实现源码转补码关于这个仓库 这个存储库包含我所有与 Spring Batch 相关的工作: blog : 我关于 Spring Batch 的blog源代码 issues :(尝试)重现 Github 和 StackOverflow 上报告的问题 diagrams :从 Spring ...
什么叫刷新为什么要刷新说明刷新有几种方法。 答:动态RMA在2ms内,将所存信息读出再重新写入,这一过程称为刷新,刷新是一行一行进行的,由CPU自动完成。动态RAM靠电容存储电荷原理存储信息,电容上的电荷要放电,...
我可以用它做什么? 符号求解器可以将代码中的符号与其声明相关联。 这对于验证表达式的类型或查找符号的用法(如字段或局部变量)是必要的: 考虑一下: int a = 0 ; void foo() { while ( true ) { String a = " ...
●采用n位补码(包含一个符号位)表示数据,可以直接表示数值(1)。 (1)A.2n B.-2n C.2n-1 D.-2n-1 ●以下关于采用一位奇校验方法的叙述中,正确的是(2)。 (2)A.若所有奇数位出错,则可以检测出该错误但...
typedef struct int100{ //100位长整数,以补码存储 __int64 low; //低0 ... 2^51-1位 51 .. 63 位置空,作溢出时保留数据用 __int64 top; //高0 ... 2^61-1 //__int64 sign; //符号位在...
存储地址是存储器存储单元的编号,CPU要存取某个存储单元的信息,一定要知道这个存 储单元的地址,并通过地址线中的地址信号去找到这个地址单元。 11. 计算机的硬件和软件是互相依存、互相支持的,硬件的某些功能...
如果要表示大于32767的整数,则需要在printf里用%ld,而不能再用%d了,因为%d只能表示最大到32767 第五关: 一个整常量后面加上u或U,就表示此常量为无符号数。如12345u或12345U,则计算机就会在内存里按unsigned ...