当前位置: 首页 > news >正文

原码、补码、反码、移码是什么?

计算机很多术语翻译成中文之后,不知道是译者出于什么目的,往往将其翻译成一个很难懂的名词。

奇怪的数学定义

下面是关于原码的“吐槽”,可以当作扩展。你可以不看,直接去下一章,没有任何影响。
原码的吐槽放在前面是防止读者看完原码,然后看半天才看到补码,影响阅读体验。

某些书描述“原码”的时候很“奇怪”,你可能在某些书上见到过下面这样很难理解的描述(下图截自原码 - 维基百科):
请添加图片描述

这玩意是数论里的等价类或者群论里的空间的表达方式,也就是计算机里常出现的“模运算”。或者还有个更高级的名字:散列(因为很多散列算法就是模运算,然后用的等价类的思想)。

等价类:3 mod 21 mod 2的结果都为1,所以都等于[1],也就是31都是关系mod 21等价类。

那上面的那一堆是什么意思呢?

以整数原码为例,X是一个数,范围不定。

[+1011]的意思是和+1011等价的所有数:
X m o d 2 n = 1011 X mod 2^n = 1011 Xmod2n=1011

比如 n > 4 n>4 n>4的时候 2 n > 0 b 1111 2^n>0b1111 2n>0b1111
1011 m o d 2 n = 1011 ( 2 n + 1011 ) m o d 2 n = 1011 1011 mod 2^n = 1011\\ (2^n + 1011) mod 2^n = 1011 1011mod2n=1011(2n+1011)mod2n=1011

[-1011]的意思是和(2^{n-1} - 1011)等价的所有类:

( 2 n − 1 − X ) m o d 2 n = 1011 (2^{n-1} - X) mod 2^n = 1011 (2n1X)mod2n=1011

比如是 8 位的数字:
( 2 8 − 1 − ( − 1011 ) ) m o d 2 n = ( 10000000 + 1011 ) ) m o d 11111111 = 10001011 (2^{8-1} - (-1011)) mod 2^n =\\ (10000000 + 1011)) mod 11111111 = 10001011 (281(1011))mod2n=(10000000+1011))mod11111111=10001011

这是教材,不是论文,而且一般论文也不用这么说吧?

这种表达方式唯一的好处就是让你理解溢出之后该怎么处理,因为取模运算的值就是溢出后得到的值。

说实话这种表达方式就不应该出现在任何现代教材中,哪怕是很多数学分析的书都不会这样描述数的。我不知道这种用法最早出现在哪里,但是欧美一些常见的计算机组成与设计教材中没有出现过这种用法,也就是说并不是盲目学来的。

不论是“true code”还是“true form”都在英文搜索中难以找到。WiKi “有符号数处理”中,“原码”对应的是“符号及值(sign & magnitude)”,英文版直接就是“Sign–magnitude”。这玩意的在一些教材中的翻译是“符号和幅值表达法”,看看这个名字多清晰和直白。

这个方法读者理解就好,没必要学,后文也完全不使用这个方法,怎么容易理解怎么来。但计算机科学确实有很多算法使用了等价类的概念,所以如果你要走算法方向,还是要看看的。

原码

原码就是我们常用的数,在计算机中就是用二进制表示的十进制数,不论正负、不论整数还是小数。

n位原码就是用最高位(小端就是最右位)当作符号位(0为正数,1为负数),关于0对称范围内的数( − 2 n ~ 2 n -2^n~2^n 2n2n),比如-4~4-16~16,范围的两个端点关于0对称,正负数的个数相同。

补码(2’s complement)

n位补码就是用最高位(小端就是最右位)当作符号位(0为正数,1为负数)关于0不对称范围内的数( − 2 n − 1 ~ ( 2 n − 1 − 1 ) -2^{n-1}~(2^{n-1}-1) 2n1(2n11)),比如-16~15,范围的两个端点关于0不对称。

这里概念很容易和和其他码搞混,比如原码。

但其实只用记住一个关键点:补码的-11111,而原码是1001

换言之,从零值的“生长”来说:

  • 原码相当于少一位(最大的那位)的无符号数。抛开符号位-xx的表达是一样的,所以上下限的绝对值是一样的。
  • 补码从0开始增减,0b0000-1,借位算出是0b1111。但是+1增的时候,要注意不能让最大位为1,所以上限比下限绝对值少1

补码是现在主流的格式,所以各种考试也主要考补码。所以只讲一下补码的计算。

补码计算的时候,加减法要带着符号位进行,乘除法就是左移补0,右移补符号位

比如:

  • 1011*2,得到的是0110
  • 1011/2,得到的是1101
  • 0011+0011,也就是3+3=6=0110
 0011
+0011
-------0110
  • 0011-0111,也就是3-7=-4=1100
 0011
-0111
-------1100

用加减法可以很容易得到-x对应的二进制,反之亦然。

举个例子,我要计算出1111 0100的的十进制,那么可以先计算出和0(0000 0000)的差(前 4 位相同,甚至可以不用写):

 0000 0000
-1111 0100
-----------0000 1100

得到12,加上符号-(原二进制符号位为1,也就是负的),那么最后得到-12

反之,我们想计算出-8的二进制,也就是和08(0000 1000),那么就可以:

 0000 0000
-0000 1000
-----------1111 1000

是不是很简单。

反码(1’s complement)

反码中,一个数的相反数就是按位取反,1001,这也是名字的由来。

比如1(00000001)按位取反,得到-1(11111110)。

所以反码和原码一样,是关于0对称的,所以正负数的个数相同。但是不同之处在于:反码有两个0,正0(0000)和负0(1111)。

在无符号数的反码中,x按位取反为 2 n − 1 − x 2^n-1-x 2n1x

因为无符号反码增长就是从0一直加,所以最大值是 2 n − 1 2^n-1 2n1。而按位取反就相当于从尾部往前倒。

你可以观察一下下面这个表格,再看看我的说法,你就会理解了。
请添加图片描述

反码(1’s complement)早期设备用的多,现在用补码(2’s complement)是主流,因为反码计算的时候更麻烦一些,只是在计算一些科学计算的时候更有优势罢了。

看开头的数字也可以看出顺序来(啊对,这两个英文中的数字就是版本,这你能想到哈哈哈哈)。

移码(Offset binary)

移码又称“偏移表示法”,这个方法现在是上面浮点数用的多,比如 IEEE 754。

移码从0000开始递增,依旧使用最高位位符号为,只不过这里1表示正数
0表示负数。与前面的几种方法相反。

有符号移码最小的负数是0000,最大的整数是111101000

这里可能好奇名字中“偏移”的意思,其实就是“给数加上一个偏移数后,使其具有非负的表达形式”。

比如上面的0,加上一个偏移1000,得到的就是1000,也就是0,非负。

关于这部分,浮点数中再细说吧。

希望能帮到有需要的人~

参考资料

《Computer Organization and Design MIPS Edition: The Hardware/Software Interface Fifth Edition》:如果你要学习计算机结构的话,这本书要比国内的很多教材好,但是翻译的确实不太行。

原码 - 维基百科

Signed number representations - 维基百科

相关文章:

  • 如何理解 Composition API 和 Options API
  • Linux C++ realpath函数crash的解决方法
  • Spock单元测试框架使用介绍和实践
  • linux中当前目录、上级目录、上上级目录表示方法
  • python—爬虫爬取电影页面实例
  • AI 绘画|Midjourney设计Logo提示词
  • Unity | AssetBundle
  • 【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 卢小姐的生日礼物(200分) - 三语言AC题解(Python/Java/Cpp)
  • 哪些企业适合做ISO27001信息安全管理体系?
  • 定制QCustomPlot 带有ListView的QCustomPlot 全网唯一份
  • SpringAI简单使用(本地模型+自定义知识库)
  • Linux处理文件sed
  • Java 新手学习线路,Java 学习路线是怎样的?
  • uniapp自定义tabBar
  • unity2022 il2cpp 源码编译
  • 【刷算法】求1+2+3+...+n
  • css的样式优先级
  • JavaScript异步流程控制的前世今生
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • JS笔记四:作用域、变量(函数)提升
  • Mysql5.6主从复制
  • Next.js之基础概念(二)
  • ng6--错误信息小结(持续更新)
  • Sass 快速入门教程
  • 高程读书笔记 第六章 面向对象程序设计
  • 老板让我十分钟上手nx-admin
  • 爬虫模拟登陆 SegmentFault
  • 前嗅ForeSpider中数据浏览界面介绍
  • 区块链技术特点之去中心化特性
  • 区块链将重新定义世界
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用API自动生成工具优化前端工作流
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 通信类
  • 一道闭包题引发的思考
  • 译有关态射的一切
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 你对linux中grep命令知道多少?
  • 【干货分享】dos命令大全
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​油烟净化器电源安全,保障健康餐饮生活
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (7)svelte 教程: Props(属性)
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (二)c52学习之旅-简单了解单片机
  • (二)JAVA使用POI操作excel
  • (六)激光线扫描-三维重建
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • (转)拼包函数及网络封包的异常处理(含代码)
  • ***详解账号泄露:全球约1亿用户已泄露