关于机器码中的原码和反码以及补码的几个问题

本文是撰写于笔者正式学习计算机原理前。当然本人于伯克利的CS61A课程中已经有一个初步的认识,但是今天有机会仔细思考一番,作出以下记录,权当学习笔记,必多有粗陋之处,还望读者海涵~

首先是定义:

计算机有三种码:原码(true form)、反码(Inverse form)和补码(2's complement):

原码是什么?

原码就是原码(true form)是一种计算机中对数字的二进制定点表示方法。 原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。

反码和补码是什么?

反码表示规则为:如果是正数,则表示方法和原码一样;如果是负数,符号位不变,其余各位取反,则得到这个数字的反码表示形式。

所以为什么要这样呢?

很简单,当然是因为一个正数的原码计算机可以直接读懂。如果一个正数加上一个负数,怎么办?

想当然地说:那我们可以直接加减呀

比如1_100+0_001=1_101

然而,这个东西怎么理解????

用十进制数表示:-4+2=-5吗(笑)

那么我们就需要引入反码和补码了

正数反码不需要改变,而负数的反码就是将第一位不变,之后的所有位数统统翻转(0变1,1变0)

很简单,原码加反码等于1_010 1_010 如果这个时候加上1,那我们就能得到0_000啦!!!

所以,如果我们要表示一个负数,那就将这个数字先写成反码,然后再加上1,也就是补码啦!

有什么好处呢?

刚刚介绍了一个好处,那就是通过这个负数补码,我们可以计算正数加负数了!!! 比如0_111+1_001=1_000!而1_001是1_111的补码,你用十进制数验证一下,是不是11+(-11)=0呢!!!!

有了正数加负数的定义,易得出结论:只要有加法,我们就可以定义减法了!反正减法只要改一下减数的符号就行了

然而,我们发现有一个问题……

那就是0_0000和1_0000怎么理解呢?一个是正零另一个是负零吗?

但是零只能有一个补码,否则一个数对应两个机器码,计算机就脑子乱了。

那我们认为规定0,就是0_000,或者0_000 0000 或者0_000 0000 0000……

好的,那么所谓的“负0”怎么办?

我们先看一看1_111到1_000的范围:如果不用补码来理解,那就是负7到负0,对吧!

然而负8,也就是1_000 1000怎么办?如果我们采用补码,岂不是1_111 0111+1=1_111 1000! 取后四位不就是1_000吗!!!

以此类推,如果把1_111 和 1_000全看成补码,那么这个范围岂不是负8到负1!

与0_000到0_111表示的0到7完全不冲突!

因此我们发现如果采用补码,那么我们还能解决计算机中“两个0”的问题(Oh Yeah!)

当然,你可能会说,那么计算机心中的0就是正数咯!呃……理论上是这么说可以,因为计算机看到零就是正,看到一就是负

 

好的,希望看到这里,你已经对这三种码有了初步的认识!

再次膜拜一下想出这个方法的人,要我凭空想一个编码系统我是肯定想不出来的(跪了)

 

参考资料:

Kaka的知乎专栏:https://zhuanlan.zhihu.com/p/105917577

百度百科关于原码、反码和补码的词条:https://baike.baidu.com/item/原码/1097586?fr=aladdin;https://baike.baidu.com/item/反码#1_3;https://baike.baidu.com/item/补码

 

posted @   M1stF0rest  阅读(473)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示