⼆进制的补码
今天在学习C Primer Plus(第五版)中⽂版.pdf的时候遇到这么个问题,先上代码:
#include <stdio.h>
#define PAGES 336
#define WORDS 65618
int main(void)
{
short num = PAGES;
short mnum = -PAGES;
printf("num as short and unsigned short:%hd %hu\n",num,num);
printf("-num as short and unsigned short:%hd %hu\n",mnum,mnum);
printf("num as int and char:%d %c\n",num,num);
printf("WORDS as int,short,and char:%d %hd %c\n",WORDS,WORDS,WORDS);return 0;
}
结果:
num as short and unsigned short:336 336
-num as short and unsigned short:-336 65200
num as int and char:336 P
WORDS as int,short,and char:65618 82 R
请看我标红的部分,其实我蛮想不明⽩的,为什么-336的⽆符号整数是65200呢?书上说是2的补码(书中描述):数字0到32767代表它们本⾝,⽽数字32768到65535则代表负数,65535代表-1,65534代表-2,依次类推,因此-336由65536-336,也即65200来表⽰;本宝宝表⽰真⼼没看懂啥意思,然后就在⽹上各种⼆进制的补码是啥意思,下⾯咱们就来看看什么是⼆进制的补码
我试验的计算及环境假设是8位的,那接下来我就拿计算机是8位作基础来讲解:
⼀、负数在计算机中如何表⽰
之前我写了⼀篇博客,⾥⾯是计算c语⾔整数类型的取值范围的额,⼆进制中区分正负数的⽅法是看⼆进制的最⾼位是0还是1,1为负数,0为正数
⽐如:127的⼆进制是01111111,⽽-127的⼆进制是 10000001(011111111 - 先取反,再加1 ->10000000+1 = 10000001),从这⾥可以看出127的最⾼位是0,⽽-127的最⾼位是1
⼆、什么是⼆进制补码
取⼀个数的⼆进制补码需要两步:
1>.每个⼆进制位都取相反的值,也就是⼆进制位是1的,补码就是0,⼆进制位是0的,补码就是1
2>.再把取反的⼆进制数转换成⼗进制,加上1,最后的结果就是这个数的补码的⼗进制数
负数二进制补码运算法则 举例:取-127的⼆进制补码(8位机)
⼆进制数:01111111
补码:10000000
结果:补码 10000000 + 1 = 10000001(129)
也就是说-127在计算机(8位机)中10000001(写到这⾥,我突然有点明⽩C Primer Plus书中描述的啥意思:0-127代表它本⾝,128-255代表负数,那-127就等于256-127=129)
那可能很多⼈会说:为什么是这样啊?虽然知道怎么计算了,但是不知道为什么是这么计算的,那么接下来就来说说⼆进制补码的原理
三、⼆进制补码的原理
那⼤家都知道负数怎么来的,⽐如:A-B,那A⽐B⼩,结果就会是负数,这就有很多情况了,咱不讨论,就⽐如给你⼀个负数,那么最直接的你肯定会想到⼀个表达式了,⽐如给你个-127,那表达式就是0-127的来的,那我们把他转换成⼆进制来运算⼀下:
预想结果:-127
⼗进制表达式:0-127
⼆进制表达式:00000000(0) - 01111111(127)
以前⼩学数学当被减数⼤于减数的时候都要向上借⼀位来减的,那么接下来就是借位()
重点:这⾥计算的时候⼆进制的位数是有规定的,⽐如-127,它是1111111 由7个1的⼆进制,那同学就⽤7个0的⼆进制去减,结果借⼀位变成了10000000(128)-1111111(127) = 1,然后在加1等于2,结果-127的补码就是00000010(2),这样可是错的,⼀定要遵守⼀个标准,那就是当前计算机是多少位的就借多少位加1位,那么⽐如-10是1010,就是00001010,借位就得在第9位上借,也就是100000000,结果就是246(11110110)
借位进⾏运算:
1>.100000000(256) - 01111111(127) = 10000001(129)
2>.100000000(256) = 11111111(255) + 1;
11111111(255) - 01111111(127) = 10000000(128)
10000000(128) + 1 = 10000001(129)
上⾯就是⼆进制补码的简单计算过程
四、⼆进制补码有哪些好处呢?
感觉不就是⼀个负数⽽已,⾮要搞的这么弯弯绕,我反正是晕了,那接下来就看下⼆进制补码的好处
那我们之前说的判断最⾼位是1还是0来区分正负,那接下来我们就⽤两种表⽰法来计算作⽐较:
举例:-10
表达式:20 + (-10)
1>.最⾼位区分正负:-10的⼆进制数为10001010
⼆进制计算:00010100 + 10001010 = 10011110
10011110转换成⼗进制是30,根据最⾼位区分正负,结果就是-30
2>.再来看看⼆进制补码的⽅式进⾏计算:-10的⼆进制补码(11110101 + 1 = 11110110(246))
⼆进制计算:00010100 + 11110110 = 100001010
⽽咱们刚才已经说了,假设计算机是8位的,那么这个结果超过8位,第九位会被舍弃,也就是00001010,结果就是10
五、为什么正数加法适⽤于⼆进制补码呢?
接下来我们求证⼀下X-Y(x + (-Y))这个表达式,相信⼤家就明⽩了(8位机)
Y的⼆进制补码由上⾯的讲解⼤家都知道是:(11111111 - Y) + 1 ,所以也就是X加上Y的⼆进制补码,表达式可以写成如下格式:X + (11111111 - Y) + 1
得到这个表达式就好办了,接下来我们分成两种情况来解释:
1>.那就是X⼩于Y,那么结果肯定是个负数了,我们采⽤⼆进制的补码的逆运算,求出它对应的正绝对值,再在前⾯加⼀个负号就可以了
第⼀步:计算Z、X、Y的⼆进制补码的表达式 Z = -((11111111 - Z) + 1);X = (11111111 - X) + 1;Y = (11111111 - Y) + 1;
第⼆步:根据表达式X + (11111111 - Y) + 1来替换计算:-( ( ( 11111111 - X) + 1 ) - ( ( 11111111 - Y ) + 1 ) ) = -(11111111 - X + 1 - 11111111 + Y - 1) = -( -X + Y) = X - Y;
2>.X⼤于Y,那结果肯定是正数,那意味着Z肯定⼤于11111111,那根据8位机,第九位溢出了,就要舍去,表达式为(不太明⽩...):
Z = Z - 100000000 = X + (11111111 - Y) + 1 - 100000000 = X - Y;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论