源码、反码、补码
-
数字在自然界中抽象出来的时候,是没有正数和负数的概念的(一个人,两个人,而没有负一个人);
计算机保存最原始的数字,也是没有正负概念的,叫无符号数;
我们在内存中分配8位(一个字节)去存放无符号数字,是下面这样的:
-
后来生活中为了表示“欠别人钱”这个概念,从无符号数中,划分了正数和负数;
为了表示正与负,在计算机中,人们发明了源码,把生活中的正负概念表示出来;
把二进制左边的第一位,用来表示符号,正用0来表示,负用1来表示;
- 但是使用原码的方式,方便了我们人类,却苦了计算机;
我们希望(+1)+(-1)=0,但是计算机只能算出0001+1001=1010(-2)
为了解决“正负相加等于0”的情况,在“原码”的基础上,人们发明了“反码”
反码表示方式是用来处理负数的,符号位不变,其余位数取反(0变为1,1变为0);
当“原码”变成“反码”时,完美解决了“正负相加等于0的情况”;
(+1)+(-1)=0001+1101=1111=-0
- 还有一个问题,在正数与反码中,有两个0:+0和-0;为了解决这一个问题,又发明了“补码”;
“补码”的意思是,在原来“反码”的基础上,再补充一个新的代码,即加+1;
我们要处理“反码”中的-0,当1111补上一个1之后边城了10000,丢掉最高位就是0000,搞好就是正数中的0;这样就解决了+0和-0同时存在的问题;
另外正负相加等于0也解决了;
同时我们失去了-0,也多了一个-8;
- 结论:补码就是保存正负数最好的方案。
八位的有符号数
十进制 | 二进制 | 十进制 | 二进制 |
---|---|---|---|
0 | 0000 0000 | -1 | 1111 1111 |
1 | 0000 0001 | -2 | 1111 1110 |
2 | 0000 0010 | -3 | 1111 1101 |
3 | 0000 0011 | -4 | 1111 1100 |
.. | .... .... | .. | .... .... |
124 | 0111 1100 | -125 | 1000 0011 |
125 | 0111 1101 | -126 | 1000 0010 |
126 | 0111 1110 | -127 | 1000 0001 |
127 | 0111 1111 | -128 | 1000 0000 |
算数运算
符号位参与运算,接受来自低位的进位,永远能忠实的表示结果的正负;
正数 + 正数 = 正数
120 + 5 = 125
计算结果01111101就是125,所以没有溢出
正数 + 正数 = 负数
120 + 10 = 130
计算结果10000010是-126,计算结果明显不正确,所以产生了溢出;
负数 + 负数 = 负数
(-120) + (-3) = (-123)
计算结果10000101是-123,计算结果正确,所以没有溢出;
负数 + 负数 = 正数
(-120) + (-9) = (-129)
计算结果01111111是127,计算结果不正确,所以产生了溢出;
正数 + 负数
(-127) + 3 = (-124)
计算结果10000100是-124,计算结果正确,没有产生溢出;
溢出与进位
处理器内部以补码表示有符号数,8个二进制位能表达的正数范围是+127-128,16位表达的范围是+32767-32768,如果运算超出了这个范围,就产生了溢出;有溢出,表明有符号数的运算结果不正确;
例如:
3AH + 7CH = B6H ; 58 + 124 = 182
182已经超出了127~-128这个范围,所以产生溢出;另外补码B6H的值是-74,显然运算结果也不正确;
溢出标志和进位标志是两个意义不同的标志;
- 进位标志:表示无符号数运算结果是否超出范围,运算结果仍然正确;
- 溢出标志:表示有符号数运算结果是否超出范围,运算结果不正确;
网友评论