原码、反码、补码

一、机器数和真值

1.1、机器数

对有符号数而言,符号的“正”、“负”机器是无法识别的,但由于“正”、“负”恰好是两种截然不同的状态,如果用“0”表示“正”,用“1”表示“负”,这样符号也被数字化了,并且规定将它放在有效数字的前面,即组成了有符号数。
把符号“数字化”的数称为机器数,而把带“+”或“-”符号的数称为真值。
机器数包含原码、补码、反码、移码。

1.2、真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。将带符号位的机器数对应的真正数值称为机器数的真值。

二、原码, 反码, 补码

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

2.1、原码

原码是机器数中最简单的一种表示形式,符号位为 0 表示正数,符号位为 1 表示负数,数值位即真值的绝对值。故原码表示又称为带符号的绝对值表示。
如 8 位二进制:

[+1]= 00000001
[-1]= 10000001

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

[1111111101111111]
即:[-127 , 127]

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

2.2、 反码

反码的表示方法为:正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

[+1] = [00000001]= [00000001][-1] = [10000001]= [11111110]

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

2.3、 补码

补码的表示方法为:正数的补码就是其本身,负数的补码是反码 + 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) = [00000001]+ [10000001]= [00000001]+ [11111110]= [11111111]= [10000000]= -0

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

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

1-1 = 1 + (-1) = [00000001]+ [10000001]= [00000001]+ [11111111]= [00000000]= [00000000]

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

(-1) + (-127) = [10000001]+ [11111111]= [11111111]+ [10000001]= [10000000]

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

使用补码, 不仅仅修复了 0 的符号以及存在两个编码的问题,而且还能够多表示一个最低数。这就是为什么 8 位二进制,使用原码或反码表示的范围为 [-127, +127],而使用补码表示的范围为 [-128, 127]。
因为机器使用补码,所以对于编程中常用到的 32 位 int 类型,可以表示范围是:[ − 2 31 -2^{31} 231, 2 31 2^{31} 231-1] 。因为第一位表示的是符号位,而使用补码表示时又可以多保存一个最小值。

原码反码补码计算口诀是: 1. 原码:符号位加上真值的绝对值。 2. 反码:将原码中的符号位保持不变,其余位取反。 3. 补码反码加1。 例如,对于一个8位二进制数,如果要计算其反码,可以按照以下步骤进行: 1. 将符号位保持不变。 2. 将其余位取反。 对于补码的计算,可以按照以下步骤进行: 1. 先计算其反码。 2. 在反码的基础上加1。 这样,就可以得到原码反码补码的计算结果。 #### 引用[.reference_title] - *1* [原码, 反码, 补码的基础概念和计算方法](https://blog.csdn.net/Chinajsczlymyc/article/details/126910306)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [(转)java 原码反码补码计算 以及 取反运算,原码反码补码运算公式](https://blog.csdn.net/PacosonSWJTU/article/details/128604733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [原码,补码,反码概念和计算方法详解](https://blog.csdn.net/qq_39541098/article/details/122729622)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zaiyang遇见

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值