原码,补码,反码 和 有符合,无符号 整数知识总结
原码 (true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011
原码不能直接参加运算,可能会出错。例如数学上,1+(-1)=0,而在二进制中原码00000001+10000001=10000010,换算成十进制为-2。显然出错了。所以计算机并不是以原码的形式存储整数的。
百度百科:https://baike.baidu.com/item/%E5%8E%9F%E7%A0%81/1097586?fr=aladdin
反码:正数的反码与其原码相同;负数的反码是对正数逐位取反,符号位保持为1。例如对于二进制原码10010求反码:11101。
例如,我们用8位二进制表示一个数,+11的反码为00001011(和原码一样),-11的反码就是1111 0100(把-11的原码10001011 符号位保持1,数值为取反)
虽然反码能存储数值,但是我们很容易可以看到,这样存储方式很不容易被人类思维理解。所以多数计算机不采用反码表示数值
百度百科:https://baike.baidu.com/item/%E5%8F%8D%E7%A0%81/769985?fr=aladdin
补码:正整数的补码是其二进制表示,与原码相同。求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
例如,我们用8位二进制表示一个数,+11的补码为00001011,-11的补码就是1111 0101(把-11的原码10001011 符号位保持1,数值为取反,得到数之后再+1)。
从上面的例子可以看出,对于负数来说 , 补码=原码的反码+1,对于正数来说 补码=原码=反码。
我们用4个Bit 来做个示例:
十进制数 | 原码 | 反码 | 补码 |
+7 | 0111 | 表示方式不变 | 表示方式不变 |
+6 | 0110 | 表示方式不变 | 表示方式不变 |
+5 | 0101 | 表示方式不变 | 表示方式不变 |
+4 | 0100 | 表示方式不变 | 表示方式不变 |
+3 | 0011 | 表示方式不变 | 表示方式不变 |
+2 | 0010 | 表示方式不变 | 表示方式不变 |
+1 | 0001 | 表示方式不变 | 表示方式不变 |
+0 | 0000 | 表示方式不变 | 表示方式不变 |
-0 | 1000 | 1111 | [1]0000 |
-1 | 1001 | 1110 | 1111 |
-2 | 1010 | 1101 | 1110 |
-3 | 1011 | 1100 | 1101 |
-4 | 1100 | 1011 | 1100 |
-5 | 1101 | 1010 | 1011 |
-6 | 1110 | 1001 | 1010 |
-7 | 1111 | 1000 | 1001 |
-8 | 超出4个bit所能表达范围 | 超出4个表达范围 | 1000 |
其实可以举例简单说明,
补码加法:51+41,51补码=0011 0011,41补码=0010 1001。所以 00110011+00101001=01011100(十进制92)
补码减法:51+(-41),51补码=0011 0011,(-41)原码= 1010 1001,反码=1101 0110,补码=1101 0111。所以 00110011+11010111=[100001010] 00001010 (十进制10)
注:因为计算机中运算器的位长是固定的(定长运算),上述运算中产生的最高位进位将丢掉,所以结果不是100001010,而是00001010。
-
数的表示在数的表示上通过人为的定义来消除编码映射的不唯一性,对转换后的10000000强制认定为-128。当然对原码和反码也可以做这种强制认定,那为什么原码和反码没有流行起来?原码和反码没有流行起来,是因为在数的运算上对符号位的处理无法用当时已有的机器物理设计来实现。由于原码和反码在编码时采用了硬性的人工设计,这种设计在数理上无法自动的通过模来实现对符号位的自动处理,符号位必须人工处理,必须对机器加入新的物理部件来专门处理符号位,这加大了机器设计难度,加大的机器成本,不到万不得已,不走这条路。
-
数的运算设计补码时,有意识的引用了模运算在数理上对符号位的自动处理,利用模的自动丢弃实现了符号位的自然处理,仅仅通过编码的改变就可以在不更改机器物理架构的基础上完成的预期的要求,所以补码沿用至今。
-
自身逻辑意义的完整性补码这个编码方案要解决的是如何在机器中表示负数,其本质意义为用一个正数来表示这个正数对应的负数。所谓-20的补码是指:如何在机器中用补码形式表示-20。具体过程是这样的:将20的二进制形式直接写出00010100,然后所有位取反变成11101011,再加1变成了11101100。最简单的补码转换方式,不必去理会转换过程中的符号位,只关注转换前和最终转换后的符号位就行了。那么对11101100求出其补码又具有什么现实含义呢?对一个数求补,逻辑过程是对这个数的所有的二进制位按位取反再加1。现实含义是求出这个数对应的负数形式。对11101100求补就是求出这个数对应的负数的形式,直接操作下11101100,先所有位取反00010011,再加1就成了00010100。对11101100求出其补码的含义:11101100按照现行补码码制表示的有符号数是-20,对于-20求补就是求出其对应的负数-(-20),现实中-(-20)是+20,那么求补运算的结果符合现实情况吗,00010100转换成有符号数正是+20,这就说明了补码自身逻辑意义是完整的,是不会自相矛盾的。
-
最后,补码的总前提是机器数,不要忘了机器数的符号位含义,最高位为0表示正数,最高位为1表示负数,而最高位是指机器字长的最左边一位。字节数100B,最高位为00000100中的最左边的0。
最后再强调一下,计算机内存都是以补码的形式存储整数的。
百度百科:https://baike.baidu.com/item/%E8%A1%A5%E7%A0%81/6854613?fr=aladdin
了解了原码反码和补码,之后,我们就可以比较容易理解有符号和无符号整数的概念了
有符号整数:正整数+负整数+0
无符号整数:正整数+0
当数据类型是有符号类型时,就需要用一个位来标记正负号,当数据类型为无符号整数时,就不需要用位来标记正负。有无符号取值范围对比如下:
所以一个字节Byte=8bit 的范围就可以知道
有符号 |
无符号 |
|
最大值 | 0111 1111=127 | 1111 1111=255 |
最小值 | 1000 0000=-128 | 0000 0000=0 |
有符号:0111 1111 = 2^6+2^5+2^4+2^3+2^2+2^1+2^0 = 127; ==> 范围是 -128 ~ 127
无符号:1111 1111 = 2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0 = 255;==> 范围是 0 ~ 255
但是我们或许还有一个疑问。1111 1111在有符号时 = -1,在无符号时 =255 。那是不是矛盾了呐?
(以下内容是我个人的理解,不一定完全正确,仅供参考)
我觉得可以这么理解,计算机怎么存储整数,是和你定的数据类型有关。
C#中定义的整数数据类型有
|
有符号 |
无符号 |
8位 |
SByte ,sbyte, |
Byte ,byte |
16位 |
Int16,short |
UInt16,ushort |
32位 |
Int32,int |
UInt32,uint |
64位 |
Int64,long |
UInt64,ulong |
对于sbyte类型来说-1在计算机内存中就用1111 1111来存储,对于byte类型来说255在计算机内存中就用1111 1111来存储。
posted on 2019-09-21 01:02 IT_xiaozhang 阅读(3155) 评论(0) 编辑 收藏 举报