作者:余小小
日期:2021-10-02
原码
原码(true form)是一种中对数字的定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
参考:
简单的说:原码就是一个二进制,把所有数值转成二进制的样子
反码
反码是数值的一种,如linux平台的目录和文件的默认权限的设置umask,就是使用反码原理。
参考:
简单的说:反码就是二进制后进行反向取值后新生成的二进制
补码
在系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理
参考:
简单的理解:源码取反后+1,则就是反码+1,这个1就是数字上的1,一个整数值。补码才是计算机正真存储负数的方式
符号位
符号位都是用0表示“正”,用1表示“负”
所谓符号,就是数学中的正数和负数,在计算机中也是有正数和负数值区分的,识别方式正是通过符号位来判断
那么符号位,就是在二进制的情况下左边的一位也就是最高次位
数值位
则是存储数值的位置,简单的理解,在二进制的8位中,就是除了符号位,其他的都叫做数值位。
负数十进制转二进制
我们的十进制数-22怎么转换成二进制呢?
原始粗暴的方式,方式一
-
首先我们直接先找到22的二进制数,即用22疯狂除2结果是01101倒过来就是00010110(在每次我们求二进制的时候,建议各位还是反过来验算一下。)
-
这里我们已经得到了22的二进制数00010110(这里的二进制数是22的原码)
-
由于计算机里,左边的一位也就是最高次位是表示的正负号也就是0正1符。可以看到00010110左边的第一位是0,那么表示当前数是一个正数。
-
那么得到了22的原码后,可以直接得到-22的原码,即10010110。(因为22的原码0,0010110这里的第一个0就是一个符号位,直接变成1就得到了1,0010110即-22的原码),但是没有必要获得-22的原码,因为真正存储的是负数的补码。
-
但是计算机不会直接认识它是负数的,所及还需要获得-22的反码;
-
现在我们需要用到反码(就是把0换成1,把1换成0)的知识咯。之前求到的1,0010110反过来且符号位不变就是11101001;这里就是得到的反码,(因为已经获得了负数的原码了,那么符号位不变,如果是获得的正数原码,那么符号位依旧是要改变的)
-
然后在加1获取补码,这里的+1,则是在二进制的基础上进行+1的数值运算,运算是从右边开始,11101001末尾的1加1后就是2了,那么则移动位置成11101010
-
所以-22二进制表达式就是11101010(这个补码才是计算机存储负数的方式)
上机操作,方式二
这里我打印的是32位,不同的操作系统打印的二进制不同
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b[100];
itoa(-22,b,2);
printf("-22转成二进制:%s",b);
}
总结负数转二进制
-
寻找原码:获取相应的正数的二进制,比如-22,那么就先算22的二进制
-
获得反码:除了最左边的符号位不变,其他的都取反
-
获得补码:将反码进行+1操作
二进制转换成十进制(负数)
原始粗暴的方式,方式一
这里还是用之前的例子为例,我们有个二进制数11101010
-
-
就得到11101001,这个反码,是当前负数的反码
-
然后将反码转换成原码就是将0和1兑换回来得到:00010110,那么这里是直接取反,是获得正数的原码。而非负数的原码,如果是负数的原码,不要忘记了符号位1,那么真的负数的原码是10010110
-
在将正数原码转换成十进制:0x2的0次方+1×2的1次方+2的2次方+2的4次方=2+4+16=22但是这里是负数的二进制转换而来,所以是-22(转换的时候运算不看符号位避免分不清)
上机操作,方式二
这个和二进制数值的数类型有关,这超过了int的范围,所以用%ld来占位
十进制占位符:(全部是小写字母)
-
%hd:对应short
-
%d:对应int
-
%ld:对应long
#include <stdio.h>
int main()
{
printf("十进制:%ld",0B11111111111111111111111111101010);
}
暂无评论内容