按位取反 补码

按位取反再加一(补码)

按位取反再加1是一个互逆运算。a取反加一,再取反加一,还等于a

------------------------------------

在计算机中,减法可以用加法来代替,用的就是补码。说道补码,就得说道“模”这个概念。假如我有一个计算机,它只有四个bit,这四个bit所能表示的值的范围用二进制表示是0000到1111,即从0到15。这样,这个计算机就只能表示这16个数,别的东西它就无法表示了。这个16就是这个计算机的“模”,在这个计算机上进行的计算只能在“模”的表示范围之内。

如果我们要计算5-3的值,我们既可以用5减去3,也可以用5加上13。这是为什么呢?这就像我们的钟表,它从1点走到12点之后,又回到了1点。我们的计算机也是,从0走到15之后,再往下走就又回到了0,就像我们转了一个圈一样。我们从5这个位置往回退3个格,就完成了5-3这个计算。我们也可以从5这个位置往前走,一直走到15,这时我们走了10个格,然后我们继续往前走,走到0,然后到1,然后就走到了2。这样,我们往前走了13个格之后,也到了2这个位置。所以说,在我们这个计算机中,减3和加13是一样的。而3+13=16,我们说在模16的系统下,3和13是互补的。

这样,我们计算5-3就可以换成5+13。3的二进制表示为0011,5的二进制表示为0101。这样,0101-0011就可以表示为0101+(-0011)。我们在计算机中都是把负数用其补码表示,-0011的补码就是10000-0011(即16-3,也就是13)。10000-0011=1+1111-0011=1+(1111-0011)=1+1100=1101。我们总说补码是“按位取反再加一”,看了上面这个式子相信大家就会明白了,其实就是把10000-0011换成了1111-0011再加1的形式。然后,0101-0011就换成了0101+1101,它们计算出来的结果为10010。由于我们的计算机只有四个bit,所以结果为0010。即,在模16的计算机中,5-3=5+13=2。


------------------------------------

先看正码表示,设N=4, -1 = 1001; -2 = 1010, -1 > -2, 但是 1001 < 1010,两种映射的编码的序性不一致

反码呢,-1=1110, -2 = 1101,  Ok,序性正确了,

然而,这里有一个问题,就是正数与负数之间,有一个1的缝隙。-1=1110, 1=0001,从循环编码的角度,这两个编码相差3:1110->1111->0000->0001。

因为正零和负零是两个数,导致两个数系的断裂。怎么办?让负数整体往正数靠拢,迈进一步(+1),负1没有了。

这就是求补的过程了。反码再加1。

我想,当初写出计算机的编码设计论文的大牛(好像是图灵还是什么的),当然有更深的考虑。但从序性和数系联系的角度,补码的发明是相当合理的。而这种合理性,我个人认为,正是其优点。

从机器实现的角度,并不算复杂,但相对反码的机器实现,还是多了+1的进位延时。

------------------------------------

任何一个数都可以表示为-a=2^(n-1)-2^(n-1)-a;

这个假设a为正数,那么-a就是负数。而根据二进制转十进制数的方法,我们可以把a表示为:a=k0*2^0+k1*2^1+k2*2^2+……+k(n-2)*2^(n-2),第(n-1)位为符号位不计算在内。

这里k0,k1,k2,k(n-2)是1或者0,而且这里设a的二进制位数为n位,即其模为2^(n-1),而2^(n-1)其二项展开是:1+2^0+2^1+2^2+……+2^(n-2),而式子:-a=2^(n-1)-2^(n-1)-a中,2^(n-1)-a代入a=k0*2^0+k1*2^1+k2*2^2+……+k(n-2)*2^(n-2)和2^(n-1)=1+2^0+2^1+2^2+……+2^(n-2)两式,2^(n-1)-a=(1-k(n-2))*2^(n-2)+(1-k(n-3))*2^(n-3)+……+(1-k2)*2^2+(1-k1)*2^1+(1-k0)*2^0+1,而这步转化正是取反再加1的规则的代数原理所在。因为这里k0,k1,k2,k3……不是0就是1,所以1-k0,1-k1,1-k2的运算就是二进制下的取反,而为什么要加1,追溯起来就是2^(n-1)的二项展开式最后还有一项1的缘故。而-a=2^(n-1)-2^(n-1)-a中,还有-2^(n-1)这项未解释,这项就是补码里首位的1,首位1在转化为十进制时要乘上2^(n-1),这正是n位二进制的模。

不能贴公式,所以看起来很麻烦,如果写成代数式子看起来是很方便的。

注:n位二进制,最高位为符号位,因此表示的数值范围-2^(n-1) ——2^(n-1) -1,所以模为2^(n-1)。上面提到的8位二进制模为2^8是因为最高位非符号位,表示的数值范围为0——2^8-1。

时间: 2024-10-10 02:55:26

按位取反 补码的相关文章

Java之&amp;0xff用法解析以及原码、反码、补码相关知识

char强转至int为什么使用0xff? 备注:在Java中采用补码形式表示二进制 如果不希望进行符号扩展,可以采用与操作.例如char c:int i = c & 0xffff:其中,char有8位,int类型有32位,采用32/8=4个f(即0xffff)做与操作,即可屏蔽符号扩展. //负整数时,前面输入了多余的 FF ,没有去掉前面多余的 FF,按并双字节形式输出System.out.println(Integer.toHexString(-2).toUpperCase());//FFF

原码-反码-补码-移码

数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,原码能表示数值的范围为 127~(-127) 原码-反码-补码-移码 原码 :二进制(开头第一个表示符号0正1负) 反码 :在原码的基础上,符号位不动,其他位取反 补码 :在反码的基础上,运算+1 移码 :在补码的基础上,符号位取反 101011(二进制)--> 原码 00101011 --> 反码 01010100 --> 补码 01010101--&

关于原码、补码、反码的理解

补下基础 -- 原码.补码.反码 -- 正数补码.反码都和原码一样, 符号位为0 -- 负数原码  符号位为1,其他位为 绝对值表示的二进制数 反码  原码符号位不变.其他位按位取反 补码 反码 + 1 反码的问题是 00000000 为0, 反码为 00000000 10000000 也为0, 反码为 11111111 这样0就有两个反码,   11111111 -127反码为 1000000 补码  反码 + 1 所以 10000000为0  反码为11111111 补码为反码+1 => 0

补码的计算

对于程序猿或者是其它搞计算机类的人员,这篇只是为了解释一下原码,反码,补码之间的计算和解释上一篇的a + -a = -1的问题!!! 首先先介绍一下整数在计算机中表示方法,数在计算机中都是用二进制表示,但是字节长度就不一定了,不同的机器可能就不一样 而且在计算机系统中,补码是最重要的编码,数值一律用补码来表示和存储 移码(又叫增码)是符号位取反的补码,一般用做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0 整数有正,有负的,所以计算机中为了表示正负,用字节的最高位来表示正负,其它位表示数

反码补码报告

关于反码补码的知识总结 基本概念 正数(定点小数.定点整数): 原码,补码,反码相同: 负数(定点小数.定点整数): 反码:保持原码符号位不变,数值位取反 补码:第一种方法给反码的最低位+1就可以啦,若数值最高位有进位则丢弃(不向符号位进位) 第二种方法以原码为基础,符号位不变,其他从最低位开始,直到遇到第一个1之前什么都不变,该位之前位依次按位取反,即(推荐) 原码: ([符号位][***][1][n*0]),其对应补码仅需对[***]部分依次取反即可. 例如,当编码总位数为8时有: +127

阅读《C++Primer》的个人记录(二)——2.1基本内置类型-关于浮点数、补码

学习第二章基本内置类型的过程中,对于书上描写的单精度浮点数和双精度浮点数的相关内容和补码的作用原理没弄清楚,经过查阅相关资料,整理如下: 现从简单的补码说起,原码:正数的原码就是它的本身,负数用最高位是1表示负数反码:正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反补码:正数的补码和原码一样,负数的补码是负数的反码加1[符号位在计算时直接参与运算]原码缺点:0有两种表示,无法处理减法反码:可以处理加减法及符号位,但0仍然有两种表示方式补码:完美解决以上问题逐条分析原码加减法运算:略

原码、反码、补码,负数表示法

原码  5 => 0b101,1 => 0b1 ,-1 => -0b1, bin(-1) 反码  正数的反码与原码相同:负数的反码符号位不变其余按位取反 补码  正数的补码与原码相同:负数的补码符号位不变其余按位取反后+1 负数表示法 数字电路的CPU中的运算器实现了加法器,但是没有减法器,减法是转换成加法 p 负数在计算机中使用补码存储,-1的补码为1111 111 原文地址:https://www.cnblogs.com/efan373/p/10434634.html

原码、反码、补码的简单转换

1.正数的原码.反码.补码是一样的 如+1011111(95)的原码.反码.补码为: 原码 0101 1111 反码 0101 1111 补码 0101 1111 2.负数的原码.反码.补码转换 以-1011111(-95)的原码.补码.反码的转换为例: (1)负数原码.反码转换 符号位不变,数值位按位取反 原码转反码 原码 1101 1111 反码 1010 0000 //符号位不变,数值位按位取反 反码转原码 反码 1010 0000 原码 1101 1111 //符号位不变,数值位按位取反

如鹏网JAVA培训笔记1(晓伟整理)

JDK(Java Developmet Kit) JRE(Java RunTime Environment)的区别: JRE只有运行JAVA程序的环境,没有开发相关的工具;JDK=JRE+开发相关的工具. 用记事本运行java程序出现的问题: //可以执行的程序 class hello { public static void main(String[] args) { System.out.println("Hello World!"); } } //自己编写的为什么不能执行?? c