一、原码、反码、补码和移码的一般求法

码制 一般求法
原码 符号位用0表示正数,1表示负数,其余位不变。
反码 正数的反码与原码一样,负数的反码是对它的原码(除符号位外)各位取反。
补码 正数的补码与原码一样,负数的补码是其反码尾部加1。
移码 不管正负数,将其补码的符号位取反即可。

二、移码的“真正”求法

移码:移码表示法是在数X上增加一个偏移量来定义的,通常用于表示浮点数的阶码。

如果机器字长为n,规定偏移 量为2n-1,则移码定义如下:

X 为纯整数:[X]=2n-1+X(-2n-1≤X<2n-1

X 为纯小数:[X]=1+X(-1≤X<1)

【举个栗子】

[+1]=28-1+1=129=1 000 0001

[-1]=28-1 -1=127=0 111 1111

[+127]=28-1+127=255=1 111 1111

[-127]=28-1 -127=1=0 000 0001

[+45]=28-1+45=173=1 010 1101

[-45]=28-1 -45=83=0 101 0011

[+0.5]=1+0.5=1.5=1 100 0000

[-0.5]=1-0.5=0.5=0 100 0000

[+0]=[-0]=1 000 0000


三、原码、反码、补码和移码的“由来”

1. 原码

原码:符号位用0表示正数,1表示负数,其余位不变。

对于计算机,加减乘除是最基础的运算,要设计的尽量简单。

计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂!于是科学家想出了将符号位也参与运算的方法。

我们知道,根据运算法则,减去一个正数等于加上一 个负数,即:1-1=1+(-1)=0,所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了。

在运算中,原码进行加法运算是没有问题的,但是在减法运算中会出问题,如:(D表示十进制)

1D-1D

=1D+(-1)D

=[0 000 0001]+[1 000 0001]

=[1 000 0010]

=-2D

这个结果明显是错误的!

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

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

2. 反码

反码:正数的反码与原码一样,负数的反码是对它的原码(除符号位外)各位取反。

【举个栗子】

使用反码计算 1-1 过程如下:

1D-1D

= 1D+(-1)D

= [0 000 0001]+[1 000 0001]

=[0 000 0001]+[1 111 1110]

=[1 111 1111]

=[1 000 0000]

= - 0D

发现用反码计算减法,结果的真值部分是正确的。

而唯一的问题其实就出现在“0”这个特殊的数值上。虽然人们理解上+0 和-0 是一样的, 但在这里 0 带符号是没有任何意义的,而且会有[0 0000000]原和[1 0000000]原两个编码表示 0。 于是补码出现了,解决了 0 的符号和 0 的两个编码问题,以及原码和补码进行减法运算时出现的问题。

3. 补码

补码:正数的补码与原码一样,负数的补码是其反码尾部加1。

使用补码计算 1-1 过程如下:

1D-1D

=1D+(-1)D

=[0 000 0001]+[1 000 0001]

=[0 000 0001]+[1 111 1111]

=[0 000 0000]

=[0 000 0000]

=0D

这样 0 用 0 000 0000 表示,而以前出现问题的-0 则不存在了,且在补码中 0 也只有一种唯一的表示形式。

假设机器字长为 8 位,使用补码则可以用[1 000 0000]表示-128D;

(-1)D+(-127)D

=[1 000 0001]+[1 111 1111]

=[1 111 1111]+[1 000 0001]

=[1 000 0000]

最终运算结果应为 [1 1000 0000],但由于机器字长为 8 位,最左边的“1”被丢掉了,故只剩下[1 000 0000]-1-127 的结果应该是-128,在用补码运算的结果中,[1 000 0000]就是-128。

但是注意因为实际上是使用以前的 -0 的补码来表示 -128,所以-128 并没有原码和反码表示(对-128 的补码表示[1 000 0000]算出来的原码是[0 000 0000],这是不正确的)。

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

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

假设机器字长为 n 位,则使用补码表示的最小的一个数是 -2n-1

4. 移码

移码:不管正负数,将其补码的符号位取反即可。

常用来比较大小,一般会把浮点数的阶码用移码表示。当把数值用移码表示出来可一眼看出它们的大小,这样很容易判断阶码的大小,移码可用于简化浮点数的乘除法运算。


四、原码、反码、补码和移码的取值范围

码制 定点整数 定点小数
原码 -(2n-1-1) ~ +(2n-1-1) -(1-2-(n-1)) ~ +(1-2-(n-1))
反码 -(2n-1-1) ~ +(2n-1-1) -(1-2-(n-1)) ~ +(1-2-(n-1))
补码 -2n-1 ~ +(2n-1-1) -1 ~ +(1-2-(n-1))
移码 -2n-1 ~ +(2n-1-1) -1 ~ +(1-2-(n-1))

【定点小数的取值范围的推算】

以补码为例:一个数用 n 位存储,用掉一个符号位后,还有 (n-1) 位,如果小数点在最右边,此时表示的是整数,可表示 -2n-1 ~ +(2n-1-1) 范围的数,把小数点左移 n-1 位,相当于除以 2(n-1) ,结果为:

-1 ~ +(1-2-(n-1))

同理可以将其他码制的范围求出来。


【总结】

总之,反码用来解决负数加法运算问题,将减法运算转换为加法运算,从而简化运算规则;

补码解决负数加法运算正负零问题,弥补了反码的不足。

反码与补码都是为了解决负数运算问题,跟正数没关系,因此,不管是正整数还是正小数,原码,反码,补码都全部相同。

将补码符号位取反即得到相应的移码。

# 原码、反码、补码和移码详解 # 原码、反码、补码和移码的“由来”相关推荐

  1. c语言与java负数补码,详解原码、反码与补码存储与大小

    详解原码.反码与补码存储与大小 原码: 如果机器字长为N个bit,那么一个数的原码就是N位二进制数,最高位 是符号位,1代表负数,0代表正数. 反码: 正数的反码就是原码,负数的反码就是符号位不变,其 ...

  2. 有符号数和无符号数详解(2)补码详解

    有符号数和无符号数详解(2)补码详解 1. 为什么需要补码 1.1 背景 2 补码的思想 2.1 我们希望只设计加法运算器,不用减法运算器. 2.2 现在问题是:怎么表示-1呢? 3. 补码 3.1 ...

  3. 如何将一个完整项目推到码云_怎么将本地项目放到码云(gitee)上面?图文详解

    原标题:怎么将本地项目放到码云(gitee)上面?图文详解 git的好处什么的,在此就不多赘述.现在很多公司都在用git了. 那么怎么将本地已经有的项目放到码云(gitee)上呢? 前置条件说明: 1 ...

  4. 史上最全“Git插件+码云+分支” 使用步骤详解

    版本控制也就那么回事!!! 史上最全"Git插件+码云+分支" 使用步骤详解 1.准备Git: 1.1 下载Git到本地: 首先在华为镜像云里面搜索"Git-For-Wi ...

  5. php get 返回源码,php源码 fsockopen获取网页内容实例详解

    PHP fsockopen函数说明: Open Internet or Unix domain socket connection(打开套接字链接) Initiates a socket connec ...

  6. C#高级编程——C#扩展方法+接口,定义统一的搜索接口,基于Unity(三)——图文详解加源码

    C#高级编程--C#扩展方法+接口,定义统一的搜索接口,基于Unity(三)--图文详解加源码 前言

  7. 并发编程五:java并发线程池底层原理详解和源码分析

    文章目录 java并发线程池底层原理详解和源码分析 线程和线程池性能对比 Executors创建的三种线程池分析 自定义线程池分析 线程池源码分析 继承关系 ThreadPoolExecutor源码分 ...

  8. Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载)

    Java开源生鲜电商平台-Java分布式以及负载均衡架构与设计详解(源码可下载) 说明:主要是针对一些中大型的项目需要进行分布式以及负载均衡的架构提一些思路与建议. 面对大量用户访问.高并发请求,海量 ...

  9. H264码流RTP封装方式详解

    H264码流RTP封装方式详解 文章目录 H264码流RTP封装方式详解 1 H264基本概念 2 NALU Header介绍 3 RTP封装H264码流 3.1 单一NALU模式 3.2 组合帧封装 ...

最新文章

  1. 掌握这些技巧助你轻松绘制程序流程图
  2. postgresql 比较两个时间差大于 N个小时
  3. mysql表空间名字查询_数据库表空间信息查询
  4. C#使用oledb操作excel文件的方法
  5. MikroTik ROS软路由OSPF命令配置实例
  6. Python的动态特性(类实例增加属性,动态变量类型)
  7. 【组合数学】组合恒等式 ( 八个组合恒等式回顾 | 组合恒等式 积 1 | 证明 | 使用场景 | 求组合数通用方法 )
  8. 小米8绑定账号和设备验证失败_网赚项目刚需账号答疑大集合!
  9. [java][马士兵j2se视频教程]
  10. 希捷 服务器文件丢失 原因,移动硬盘数据丢失的原因有哪些?如何进行专业的数据恢复?...
  11. ubuntu 虚拟机复制粘贴文件(文本) windows
  12. win10 支持ubuntu命令行的版本1607 产品密匙
  13. 如何官网下载Eclipse历史版本
  14. [英语] It_be_XXX_that_YYY强调句句式
  15. 【PTA】匿名内部类:实现Comparator比较器
  16. 南非世界杯-我在南非(二)
  17. 通信原理学习笔记:通信系统
  18. 成为计算机网络管理员必修课(一)
  19. java面试专题(商城面试问题)
  20. 几种MySQL高可用方案整理

热门文章

  1. 计算机信息安全op协议,2019工业信息安全技能大赛个人线上赛第一场(前5道)writeup • 旭达网络技术博客...
  2. 音乐播放上一首,下一首
  3. 国外优秀区块链创业公司梳理
  4. type-c插口,什么意思?
  5. R 软件包及其依赖包下载
  6. Windows SP 什么意思? Service Pack什么意思?
  7. Eclipse中如何设置字体大小
  8. Three.js模拟沿着路径进行运动,模拟飞机飞行,并保持运动方向
  9. 向量乘以其转置的意义
  10. FIDO与WebAuthn