二进制的计算(计算机为什么采用补码存储数据)

这里先将二进制的计算可以分为两类,加减运算与乘除运算,本篇讨论的是加减运算。

(一)预备知识——数据在计算机的存储与表示

从一个问题入手:java中byte(1字节,8位)的取值范围为:-2^7<=取值范围<=2^7-1,或者写成-128<=取值范围<=127,为什么呢?

疑问:按照我们一般认为,如果8位中一位作为符号,那么应该是11111111<=取值范围<=01111111,或者写成-127<=取值范围<=127,-128从何而来?

首先从原码讲起,原码即为计算机中对数值的二进制表示,如 5用二进制表示为0000 0101 ;

其次就是反码,顾名思义就是取反,对于正数来说,反码与原码相同;对于负数来说,反码为原码的各位取反(符号位除外),如(0011 0111)反= 0011 0111  (1101 0010)反= 1010 1101 ;

再次就是补码,计算机中,数值一律用补码表示和存储的,正数的补码与原码相同,负数的补码为“其反码+1”,如(0101 1101)补=0101 1101  (1101 0010)补=1010 1110

关于补码,我们做进一步解释:

 (1)化减为加:

由于计算中的CPU只有加法器,没有减法器,所以在计算机采用原码做减法是会存在这样的问题:对于1-1=0

看做1+(-1)=0 二进制表示 0001+1001=1001 变成了十进制的负1而不是0。补码的出现很好的解决了这个问题,由于采用补码运算,则补码加法成为:[X+Y]补 = [X]补 + [Y]补同时,补码的减法变为:[X-Y]补 = [X]补 - [Y]补 = [X]补 + [-Y]补 ;在此我们以减法为例说明补码的优势,还以上述为题为例:(0001)补+(1001)补 = 0001 + 1111 = 0000 (最高位的进位省略),这样就顺利得到了0

 (2)10000000与00000000都是零吗?——关于-128的由来

补码还解决了原码中存在两个0 的问题(即+0 和 -0),以8进制为例,java中byte的取值范围应该是-127~ -0和+0~ 127 即存在-0和+0 ,但是在两个0转换为补码后,分别为10000000和00000000,00000000它还是0,但是我们人为地规定10000000表示-128,这就是上面取值范围中-128的由来。这里再强调一下,10000000和00000000都是补码,而不是原码。

(3)一开始的问题,我们得出了“符合逻辑”的疑问,这个问题又出在哪?

其实问题出在,我们一直在用原码在看问题,而不是补码。这里先举一个我再微博中说过的例子,形象地说明一下什么是补码:

“时钟的例子:0时和6时差(10-6)=4时(顺时针),但是你也可以这样写(10+6)-12=4时(逆时针),后一个式子中的6就是“补码”,12表示“定长”,减12表示“溢出”。“定长”和“溢出”也是“化减为加”的关键。这是一个从高维空间看低维空间而变得更加简洁的典型。”

我们再用一个实际的例子说明一下如何用“高维看低维”:

类比时钟的例子,我们将表中的补码稍微转换一下位置,写在一维数轴上,再将数轴收尾相连,就形成了一个新的“时钟圆盘”。

那么我们来试试一个例子:3-1=(011-001)原码运算=(011+111)补码运算=010=2

也就是说我们可以写成3-1=2(顺时针运算),也可以写3+7-8=2(逆时针运算)

这就是用超时空理论,从高维去看地位的一种解释方法。

(二)加减法运算

(1)原码到补码的转化:符号位是要单独提取出来的,不参与“取反加一”。如:

(10000000)原转化为补码:

a.将0000000取反加一后,等于10000000

b.因为a得到的超过了七位,去掉a中10000000的1,再将题目中1给不上去。这里强调的是题目中的1和a中的1是不同的。

(2)补码的运算是连同符号位一起运算的。这里顺便提一下,二进制乘法的运算符号跟十进制乘法一样,符号位另算。

时间: 2024-10-19 12:47:34

二进制的计算(计算机为什么采用补码存储数据)的相关文章

企业采用云存储数据之前需做足准备

昂贵的硬件设备,不菲的制冷设施,再加上人员维护费用,处处都是用钱才能 堆砌出来的数据中心.这庞大的数字都预示着建立自己的数据中心是一项多么具有挑战的任务,且不说环保问题.所以企业建立自己的数据中心以达到存储数据的目 的,要付出昂贵的代价.在这种情况下,云存储的出现,就好似数据存储界的救世主降临一般,帮助企业利用零碎的成本进行数据存储,而且越来越受欢迎. 但是,也不能盲目地把数据全部迁移到云中存储,在决定采用云存储数据之前企业还是有一些准备工作要做的: 1.确保云厂商数据中心实时更新,并有行业认证

计算机为什么采用补码来进行运算

基础知识了解: 在计算机内,整数的长度是确定的,在字长为32位的计算机中,整数的长度就是32个二进制,这其中还包括了符号位(1表示正,0表示负).这里面我们为了方便描述,就假设机器字长为8位. 例如,十进制整数23,二进制真值表示为10111,其原码表示为 0001 0111. 十进制整数-23,二进制真值表示为-10111,原码表示为 1001 0111. 简而言之,源码就是最高位为符号位,其他位表示该数的绝对值 如果计算机内部采用原码表示数,那么在进行加法和减法运算的时候,最终都转化为两个绝

QString内部仍采用UTF-16存储数据且不会改变(一共9种不同情况下的编码)

出处:https://blog.qt.io/cn/2012/05/16/source-code-must-be-utf-8-and-qstring-wants-it/ 但是注意,这只是QT运行(RunTime)过程中采用的编码,并不代表源码文件里也是这样的.恰恰相反,源码文件必须是UTF8,带不带BOM都可以.我认为,虽然存储在源代码里的中文字是UTF8,但是QT在编译过程中,遇到中文会立即转换成UTF-16从而对源码里的中文字符进行编码,并存储在EXE文件里(这里对编译器来说,都是静态字符,必

hadoop之魂--mapreduce计算框架,让收集的数据产生价值 (第4篇)

  通过前面的学习,大家已经了解了HDFS文件系统.有了数据,下一步就要分析计算这些数据,产生价值.接下来我们介绍Mapreduce计算框架,学习数据是怎样被利用的. Mapreduce计算框架 如果将Hadoop比做一头大象,那么MapReduce就是那头大象的电脑.MapReduce是Hadoop核心编程模型.在Hadoop中,数据处理核心就是MapReduce程序设计模型. 本章内容: 1) MapReduce编程模型 2) MapReduce执行流程 3) MapReduce数据本地化

负数在计算机中是怎么存储

今天,发生一件非常有趣的事情. 公司同事问了我一个问题:为什么 2.0 - 1.1 = 0.89999999 呢?不应该是 0.9吗? 原来是,他问了周围一圈的同事,都给他的是同一个回答,说这是精度问题.他百思不得其解,怎么就会产生精度问题呢.再问,就没人知道原因了. 然后,我就看到了他抱着一本厚厚的书在看.拿过来一看,是一本Java书,厚厚的六百多页,这还仅是第一卷.哟呵,这是准备大干一场啊. 看在他这么努力学习的份上,还有他那对知识极度渴望的眼神.我决定,把我毕生所学传授与他. 于是,就给他

博弈树,动态规划(计算好的子问题存储起来,以后直接取用)

public class GameTree { /** * 判断剩余球数,谁能取到最后谁赢, * ,一人取一次,默认我方先取,,能否必胜,能就返回true,否则false * @param x剩余球数 * @return */ static boolean f(int x){ int[] op={1,3,7,8};//每次取球只能有四种情况 for(int i=0;i<op.length;i++){ if (x>=op[i]) { if(f(x-op[i])==false)return tru

一种存储数据的方法

写程序就是和逻辑和数据打交道,说的简单一点就是和数据打交道.说到数据,数据的存储当然是很重要的. 数据存储也是有一定的方法,在平常中,我们会用到int型来存储数据,或者bool型(C语言中没有,char型)来存储表示0,1的flag.有时候想想,如果只是简单的存储true和false的话,对于unsigned char型来说是否过于浪费了?信息论告诉我们,1bit数据就可以表示true和false,为什么不能将其存到1bit中? 那么,现在,我们开始将数据压缩. 如果有8个这样的数据,我们可以存

数据库学习笔记:第九章 存储数据:磁盘和文件

第九章 数据以磁盘块为单位存储在磁盘上.块分布于一张或多张盘片的同心环形磁道上.磁道可以在盘片的单面或双面上录制. 同一直径的所有磁道的集合称为柱面. 磁盘块的大小在磁盘初始化时可以被设置成扇区大小的倍数. 每一个记录的表面都有一个磁盘头阵列.读写一块时,磁头必须定位在块头位置. 不能并行读写的主要原因是很难保证所有磁头被精确定位在相应的磁道上. 磁盘控制器是磁盘驱动器与计算机的接口. 当数据被写到扇区时,需要计算校验和并存储在扇区上,当扇区上的数据被独处时,需要再次校验和. 寻道时间是用于移动

[安卓基础]010. 存储数据(上)

*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; text-decoration: none; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: poin