一. 机器数和真值
在学习原码、补码和补码之前,需要先了解机器数和真值的概念。
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=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]。当使用二进制补码表示时,多保存一个最小值。
四 原码, 反码, 补码 再深入
计算机巧妙地将符号位参与运算,将减法变成加法。它背后有哪些数学原理?
将时钟视为一位十六进制数。如果当前时间是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 模12=4
16 模12=4
28 模12=4
所以4、16、28 模12 全等。
负数取模
对正数进行取模运算非常简单。但是负数呢?
以下是mod运算:的数学定义
上面是截图。我找不到如何输入“删除边界”符号(粘贴到word中后代码是乱码)。下面是用'L'和'J'来代替上图:中的'removebounds'符号
x 模y=x - y L x/y J
上式的意思是:
x mod y 是x 减去y 乘以x 和y 的商的下限。
以-3 mod 2为例:
-3 模2
=-3 - 2xL -3/2J
=-3 - 2xL-1.5J
=-3 - 2x(-2)
=-3 + 4=1
所以:
(-2) 模12=12-2=10
(-4) 模12=12-4=8
(-5) 模12=12 - 5=7
开始证明
返回时钟问题:
向后2 小时=向前10 小时
向后拨4 小时=向前拨8 小时
向后拨5 小时=向前拨7 小时
注意,这里发现的模式!
结合上面学到的同余的概念。事实上,
(-2) 模12=10
10 模12=10
-2 和10 一致。
(-4) 模12=8
8 模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 (模12)
(-2)==10 (模12)
7 -2==7 + 10 (模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) 模127=126
126 模127=126
那是:
(-1)==126 (模127)
2-1=2+126 (模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) 模128=127
127 模128=127
2-1=2+127 (模128)
本文采摘于网络,不代表本站立场,转载联系作者并注明出处:https://www.iotsj.com//kuaixun/4120.html
用户评论
十分钟就能彻底理解原码、反码和补码?我拭目以待!
有7位网友表示赞同!
终于有人能把原码、反码和补码讲清楚了,期待!
有8位网友表示赞同!
十分钟?我以前理解这些概念可是花了几个小时呢,希望这次能轻松点。
有12位网友表示赞同!
原码、反码和补码一直是我的噩梦,希望能彻底搞懂!
有18位网友表示赞同!
期待能用简单易懂的方式解释原码、反码和补码。
有6位网友表示赞同!
十分钟足够吗?我觉得有点悬,不过还是可以试试。
有17位网友表示赞同!
这标题太吸引人了,十分钟就搞定,简直是福音啊!
有18位网友表示赞同!
我一直对原码、反码和补码很困惑,希望这次能找到答案。
有8位网友表示赞同!
十分钟讲清楚原码、反码和补码,这个挑战很大!
有18位网友表示赞同!
十分钟就够了?我不信!
有12位网友表示赞同!
我已经做好心理准备,十分钟就彻底搞懂原码、反码和补码!
有14位网友表示赞同!
原码、反码和补码,一直是我的痛点,希望这次能彻底搞懂。
有14位网友表示赞同!
十分钟就能理解?太棒了,我一直想彻底弄明白这些概念。
有12位网友表示赞同!
十分钟讲清楚原码、反码和补码?有点难度啊,拭目以待!
有14位网友表示赞同!
希望这次能彻底理解原码、反码和补码,再也不怕它们了!
有13位网友表示赞同!
十分钟就能搞懂?有点不相信,但还是希望可以。
有10位网友表示赞同!
对原码、反码和补码一直很头疼,期待这次能有所突破!
有15位网友表示赞同!
十分钟就能理解原码、反码和补码,这真是一个奇迹!
有14位网友表示赞同!
我之前尝试过很多次,都没有真正理解原码、反码和补码,希望这次能成功。
有16位网友表示赞同!
十分钟就能搞懂原码、反码和补码?这对我来说太重要了!
有11位网友表示赞同!