原码, 反码, 补码 详解

2023-11-12

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助!

 

一. 机器数和真值

在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念.

1、机器数

一个数在计算机中的二进制表示形式,  叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。

那么,这里的 00000011 和 10000011 就是机器数。

2、真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

 

二. 原码, 反码, 补码的基础概念和计算方法.

在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

1. 原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1] = 0000 0001

[-1] = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

2. 反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001] = [00000001]

[-1] = [10000001] = [11111110]

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

3. 补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001] = [00000001] = [00000001]

[-1] = [10000001] = [11111110] = [11111111]

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

 

三. 为何要使用原码, 反码和补码

在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

[+1] = [00000001] = [00000001] = [00000001]

所以不需要过多解释. 但是对于负数:

[-1] = [10000001] = [11111110] = [11111111]

可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001] + [10000001] = [10000010] = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001] + [1000 0001]= [0000 0001] + [1111 1110] = [1111 1111] = [1000 0000] = -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]和[1000 0000]两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001] + [1000 0001] = [0000 0001] + [1111 1111] = [0000 0000]=[0000 0000]

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001] + [1111 1111] = [1111 1111] + [1000 0001] = [1000 0000]

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000] 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000], 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

 

四 原码, 反码, 补码 再深入

计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?

将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:

1. 往回拨2个小时: 6 - 2 = 4

2. 往前拨10个小时: (6 + 10) mod 12 = 4

3. 往前拨10+12=22个小时: (6+22) mod 12 =4

2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.

所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!

现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.

首先介绍一个数学中相关的概念: 同余

 

同余的概念

两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余

记作 a ≡ b (mod m)

读作 a 与 b 关于模 m 同余。

举例说明:

4 mod 12 = 4

16 mod 12 = 4

28 mod 12 = 4

所以4, 16, 28关于模 12 同余.

 

负数取模

正数进行mod运算是很简单的. 但是负数呢?

下面是关于mod运算的数学定义:

clip_image001

上面是截图, "取下界"符号找不到如何输入(word中粘贴过来后乱码). 下面是使用"L"和"J"替换上图的"取下界"符号:

x mod y = x - y L x / y J

上面公式的意思是:

x mod y等于 x 减去 y 乘上 x与y的商的下界.

以 -3 mod 2 举例:

-3 mod 2

= -3 - 2xL -3/2 J

= -3 - 2xL-1.5J

= -3 - 2x(-2)

= -3 + 4 = 1

所以:

(-2) mod 12 = 12-2=10

(-4) mod 12 = 12-4 = 8

(-5) mod 12 = 12 - 5 = 7

 

开始证明

再回到时钟的问题上:

回拨2小时 = 前拨10小时

回拨4小时 = 前拨8小时

回拨5小时= 前拨7小时

注意, 这里发现的规律!

结合上面学到的同余的概念.实际上:

(-2) mod 12 = 10

10 mod 12 = 10

-2与10是同余的.

(-4) mod 12 = 8

8 mod 12 = 8

-4与8是同余的.

距离成功越来越近了. 要实现用正数替代负数, 只需要运用同余数的两个定理:

反身性:

a ≡ a (mod m)

这个定理是很显而易见的.

线性运算定理:

如果a ≡ b (mod m),c ≡ d (mod m) 那么:

(1)a ± c ≡ b ± d (mod m)

(2)a * c ≡ b * d (mod m)

如果想看这个定理的证明, 请看:http://baike.baidu.com/view/79282.htm

所以:

7 ≡ 7 (mod 12)

(-2) ≡ 10 (mod 12)

7 -2 ≡ 7 + 10 (mod 12)

现在我们为一个负数, 找到了它的正数同余数. 但是并不是7-2 = 7+10, 而是 7 -2 ≡ 7 + 10 (mod 12) , 即计算结果的余数相等.

接下来回到二进制的问题上, 看一下: 2-1=1的问题.

2-1=2+(-1) = [0000 0010] + [1000 0001]= [0000 0010] + [1111 1110]

先到这一步, -1的反码表示是1111 1110. 如果这里将[1111 1110]认为是原码, 则[1111 1110]原 = -126, 这里将符号位除去, 即认为是126.

发现有如下规律:

(-1) mod 127 = 126

126 mod 127 = 126

即:

(-1) ≡ 126 (mod 127)

2-1 ≡ 2+126 (mod 127)

2-1 与 2+126的余数结果是相同的! 而这个余数, 正式我们的期望的计算结果: 2-1=1

所以说一个数的反码, 实际上是这个数对于一个膜的同余数. 而这个膜并不是我们的二进制, 而是所能表示的最大值! 这就和钟表一样, 转了一圈后总能找到在可表示范围内的一个正确的数值!

而2+126很显然相当于钟表转过了一轮, 而因为符号位是参与计算的, 正好和溢出的最高位形成正确的运算结果.

既然反码可以将减法变成加法, 那么现在计算机使用的补码呢? 为什么在反码的基础上加1, 还能得到正确的结果?

2-1=2+(-1) = [0000 0010] + [1000 0001] = [0000 0010] + [1111 1111]

如果把[1111 1111]当成原码, 去除符号位, 则:

[0111 1111] = 127

其实, 在反码的基础上+1, 只是相当于增加了膜的值:

(-1) mod 128 = 127

127 mod 128 = 127

2-1 ≡ 2+127 (mod 128)

此时, 表盘相当于每128个刻度转一轮. 所以用补码表示的运算结果最小值和最大值应该是[-128, 128].

但是由于0的特殊情况, 没有办法表示128, 所以补码的取值范围是[-128, 127]

本人一直不善于数学, 所以如果文中有不对的地方请大家多多包含, 多多指点!

作者: 张子秋
出处: http://www.cnblogs.com/zhangziqiu/ 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

原码, 反码, 补码 详解 的相关文章

  • python循环经典例题_Python学习之while循环练习题

    Python自近两年在国内兴起之后 引起了很多IT界小伙伴们的注意 开始学习Python的朋友逐渐增多 但是学习时发现 循环一处开始默默的考验逻辑思维了 还是再做几个练习题来梳理复习一下吧 1 使用while循环输出1 2 3 4 5 6
  • 51单片机汇编指令

    注 Rn与Ri中n 0 7 i 0 1 另外Cy是进位位 同时也是状态位 标志位 数据传送类指令 内部数据传送指令 助记符 作用 寻址方式 机器周期 字节数 MOV A Rn 将Rn的内容传送给A 寄存器 1 1 MOV A direct
  • java selenium (一) selenium 介绍

    Selenium 是目前用的最广泛的Web UI 自动化测试框架 本系列文章 将深入简出来讲解selenium 的用法 文章的末尾处 有整个系列的链接 阅读目录 selenium 的命名 selenium 的意思是 硒 有点QTP 杀手的意
  • java Canvas画图学习小结

    主函数 package paint import javax swing JFrame public class PaintMain JFrame jFrame public static void main String args TOD
  • 函数开始处的MOV EDI, EDI的作用收藏

    函数开始处的MOV EDI EDI的作用收藏 BYTE JMP 10 0x8b 0xFF 0x55 0x8b 0xEC 0xE9 0x00 0x40 0x00 0x00 0x00 Posted on 2009 04 01 11 19 S l
  • 数据增强方法--Cutout实现及结果分析

    数据增强方法 Cutout实现及结果分析 问题背景 Cutout简介 实现细节 实验设置 代码实现 结果展示 参考文献 问题背景 近年来 深度学习在计算机视觉领域取得了相当大的进展 并且在许多具有挑战性的任务中取得了最新的性能 如对象识别
  • 怎么样可以访问外部网络对于无公网IP的阿里云ESC服务器

    新购买了3台阿里云ECS服务器 centos7 和弹性公网IP EIP 虽然是从事计算机行业的人员但俺不是计算机网络从业人员 如何将这个祖宗运行起来 并且还要能方便远程维护 唉 其间的过程及酸爽各位看官尽情脑补吧 在此特别写几篇记录一下 算
  • 数据结构 每日一练 :选择 + 编程

    目录 选择 编程 选择 A a 0 2 1 B a 1 3 C a 4 2 0 D a 0 2 2 答案 D 解析 题目给的是一个3行4列的数组 而D选项是 a 0 2 2 a 0 4 相当于取得是第1行第5列的元素 越界了 需要注意的是数
  • 剑指Offer(牛客网)-替换空格

    题目来源 https www nowcoder com practice 4060ac7e3e404ad1a894ef3e17650423 tpId 13 tqId 11155 tPage 1 rp 1 ru 2Fta 2Fcoding i
  • 网络代理技术:保障隐私与增强安全

    在当今数字化的世界中 网络代理技术的重要性日益凸显 无论您是普通用户还是网络工程师 了解如何使用代理技术来保护隐私和增强网络安全都是至关重要的 本文将深入探讨Socks5代理 IP代理以及它们在网络安全和隐私保护中的关键作用 1 Socks
  • 精益求精:如何在 React 项目中巧妙运用 Redux 并优化项目结构

    在前端开发中 React 和 Redux 已经成为构建可扩展 高效的应用程序的首选工具 本文将向您介绍如何在 React 项目中使用 Redux 并精心划分项目结构 以确保代码的可维护性和可扩展性 第一步 安装 Redux 首先 确保您的项
  • Linux下boost库的编译、安装详解

    下载boost源码 boost下载地址 解压到一个目录 tar zxvf boost 1 66 0 tar gz 执行bootstrap sh脚本 进入boost 1 66 0目录中 cd boost 1 66 0 bootstrap sh
  • Multi-Task Learning as Multi-Objective Optimization 阅读笔记

    Multi Task Learning as Multi Objective Optimization 阅读笔记 Multi Task Learning MTL Multi Objective Optimization MOO Multip
  • Android-Studio中AndroidManifest-xml文件中application标签

    AndroidManifest xml 是每个android程序中必须的文件 它位于整个项目的根目录 描述了package中暴露的组件 activities services 等等 他们各自的实现类 各种能被处理的数据和启动位置 Andro
  • 小米盒子刷鸿蒙系统,继续提升配置:小米 发布小米盒子3 增强版

    距小米盒子3发布时隔小半年之后 小米再度更新产品线 近日于官网发布小米盒子3增强版 除去外观的变化之外 新品在配置方面相较于前作也有显著的提升 首次采用了Cortex A72处理器 小米盒子3增强版售价399元 定于3月18日小米官网发售
  • ECCV2018论文,以及相关比赛地址

    原 ECCV 2018论文解读及资源集锦 10月17日更新 含全部论文下载链接 2018年08月20日 17 41 38 extremevision 阅读数 8983 div class operating div
  • 三维模型轻量化示例

    声明 本文是学习GB T 42869 2023 机械产品三维模型简化与轻量化要求 而整理的学习笔记 分享出来希望更多人受益 如果存在侵权请及时联系我们 1 范围 本文件规定了机械产品三维模型的简化要求和轻量化要求 本文件适用于机械产品三维模
  • 2019多益网络秋招视频面试算法题:将一个长度为n的数组A的元素循环右移k位

    题目 将一个长度为n的数组A的元素循环右移k位 比如数组 1 2 3 4 5 循环右移3位之后变成 3 4 5 1 2 方法一 首先考虑k 如果k能被数组长度len整除 那么数组顺序不变 可以直接输出数组 如果不能整除 得到k k len
  • PostgreSQL 时间函数 extract函数和epoch 新纪元时间的使用

    Extract 属于 SQL 的 DML 即数据库管理语言 函数 同样 InterBase 也支持 Extract 它主要用于从一个日期或时间型的字段内抽取年 月 日 时 分 秒数据 因此 它支持其关健字 YEAR MONTH DAY HO

随机推荐

  • 组合游戏系列3: 井字棋、五子棋的OpenAI Gym GUI环境

    继上一篇完成了井字棋 N子棋 的minimax 最佳策略后 我们基于Pygame来创造一个图形游戏环境 可供人机和机器对弈 为后续模拟AlphaGo的自我强化学习算法做环境准备 OpenAI Gym 在强化学习领域是事实标准 我们最终封装成
  • python面试题一个字符串是否由重复的子字符串组成

    一 给定一个非空的字符串 判断它是否可以由它的一个子串重复多次构成 给定的字符串只含有小写英文字母 并且长度不超过10000 输入 abab 输出 True 解释 可由子字符串 ab 重复两次构成 输入 aba 输出 False 输入 ab
  • 直播网站服务器带宽多少合适,开直播网速要求(开直播要多少兆宽带)

    您好 开直播也是需要分情况的吧 如果是游戏直播 打电脑游戏至少需要100M的电信宽带 体验会好一些 当然网速越高越好 如果是一般直播 上行带宽满足10M就 开直播主要是对上行速度要求比较高 有条件的话建议直接办个百兆的宽带 现在一般运营商上
  • 数据爬取与SOCKS5的完美结合

    大家好 在进行数据爬取的过程中 我们经常需要应对反爬机制和IP限制等问题 今天 我将与大家分享一种强大的工具 数据爬取与SOCKS5代理的完美结合 帮助我们更高效地获取所需数据 1 什么是SOCKS5代理 SOCKS5是一种网络代理协议 能
  • AppsFlyer 研究(十一)配置 Google Ads MCC 获取 LINK ID

    配置 Google Ads MCC 获得 LINK ID 步骤如下 1 打开Google Ads Manager accounts链接 2 点击 Create a manager account 按钮 进入创建管理账号页面 3 填写账号相关
  • 排序算法(Sort)

    预计阅读时间 10分钟 目录 第一部分 冒泡排序 介绍 过程 代码 第二部分 选择排序 介绍 过程 代码 第三部分 插入排序 简介 过程 代码 第四部分 堆排序 简介 过程 代码 第五部分 归并排序 简介 过程 代码 第六部分 快速排序 简
  • 以太坊私有链重启后账户余额清零

    以太坊私有链重启后账户余额清零 问题描述 问题原因 问题解决 这个问题一直折磨了我两天 最后终于在luo同学和lin同学的帮助下解决了该问题 问题描述 使用 geth 搭建私有链 搭建完后新建账户并通过 miner start 挖矿获得以太
  • 【STM32知识点】关于不同外设中断标志位清除的使用笔记

    在使用中断函数的时候 我们往往忘记在中断服务函数内清除中断标志位而导致一些未知错误 以下我总结了几个外设关于中断标志位的清除问题 定时器 1 在程序有使用到中断的情况下 定时器在使能之前需要先清除更新中断标志位 否则会出现定时器一使能就进入
  • RocketMQ学习笔记

    基本概念 MessageQueue 消息存储的队列 topic 由一个或多个队列组成 逻辑概念 tag msg标签 目录 基本概念 架构 分布式事务 RocketMQ事务 RocketMQ安装 下载 开启NameServer 启动Broke
  • Java获取图片传到前端,生成二维码给前端

    可以将本地图片导入然后传到前端 也可以生成一个随意长度的二维码保存到本地 也可以传到前端 可以直接通过地址栏访问 要记得导入相关pom依赖包 获取本地图片传到前端 param paramm param 功能描述 传图片 GetMapping
  • MATLAB画灰阶窗口图

    一 效果图 先上效果图 二 程序 程序段如下 注释里面都写的很清楚 Author ZXX Date 2021 10 25 Introduction 按需求生成多张图片并保存到指定文件夹下 生成多张3840 2160 w h 的含有窗口 窗口
  • 《操作系统》- 操作系统的运行环境

    目录 一 操作系统的运行机制 1 1 基本概念 1 2 时钟管理 1 3 中断机制 1 3 1 内中断有三种情况 1 3 2 中断的处理过程 1 3 3 断点调试 1 4 原语 1 5 系统数据结构 1 6 系统调用 二 操作系统体系结构
  • 启动游戏提示由于找不到xinput1 3.dll无法继续执行代码?

    最近有Win10的用户在启动游戏的时候 电脑突出弹窗提示由于找不到xinput1 3 dll无法继续执行代码 导致游戏中断无法玩耍 这个要如何解决呢 下面小编就为大家带来详细的解决方法介绍 方法一 1 大家可以自己在本站下载一个叫做 xin
  • 初试Zabbix5.0下使用官方OID监控eNSP数通设备接口状态

    笔者学习Zabbix的初衷是监控园区网络 其中一项是监控在配置MSTP下BPDU Guard Filter及DHCP Snooping后接入交换机或非法DHCP服务器后端口的状态 本篇初试一下整个流程 实验拓扑搭建 拓扑如图 其中AR1 A
  • SpringBoot使用自定义favicon.ico图标

    一直不喜欢写这东西 但是有些问题浪费我大量时间最终得以解决还是想记录一下过程 SpringBoot使用自定义favicon ico 1 找个ICO图标放在resources static目录下 名字是favicon ico 2 在html文
  • gSoap使用入门(1)----由wsdl文件生成头文件

    向导 1 1节中提供了gSoap开发包的下载地址http sourceforge net projects gsoap2 下载最新gSoap程序包 解压后在 gsoap bin win32 windowsXP下 其它操作系统就自己选择 下找
  • AngularJS form表单验证(非常全面)

    构建一个ng表单 novalidate novalidate 2 form中不能有action属性 提交交由ng submit处理 3 每个input一定要有ng model 最好有一个name方便引用 然后用require或者ng min
  • 使用命令行运行Java程序,出现中文乱码问题解决方法

    前言 对于刚刚学习Java程序的同学来说 可能会遇到使用命令行来运行Java程序的情况 当输出中文内容时 可能会出现乱码的情况 遇到这种情况不要慌 这只是你的xxx java文件保存时的编码问题 只要另存为ANSI编码就可以解决了 下面我们
  • 蓝桥杯倒计时:刷题3.31

    目录 1 打包 算法提高 二分 2 约数个数 算法提高 3 寻找三位数 算法提高 4 第二点五个不高兴的小明 5 螺旋矩阵 模拟题 5 汉诺塔 1 打包 算法提高 二分 def check k t 1 summ a 0 for i in r
  • 原码, 反码, 补码 详解

    本篇文章讲解了计算机的原码 反码和补码 并且进行了深入探求了为何要使用反码和补码 以及更进一步的论证了为何可以用反码 补码的加法计算原码的减法 论证部分如有不对的地方请各位牛人帮忙指正 希望本文对大家学习计算机基础有所帮助 一 机器数和真值