西宁市网站设计企业,wordpress显示分类目录,韩语网站建设注意事项,相册制作软件app今天我们来谈谈按位取反这件事。 简单来说#xff0c;按位取反就是先将一个数写成其二进制表达形式#xff0c;然后1变0#xff0c;0变1。下面就让我们展开深入地讨论吧#xff01; 文章目录 一、预备知识#xff1a;1. 原码#xff1a;定义#xff1a;优缺点#xff…今天我们来谈谈按位取反这件事。 简单来说按位取反就是先将一个数写成其二进制表达形式然后1变00变1。下面就让我们展开深入地讨论吧 文章目录 一、预备知识1. 原码定义优缺点 2. 补码:定义优缺点 二、按位取反:三、拓展应用1. 巧求相反数不用-2. 代替减法不用-实现减法3. 代替加法不用实现加法 一、预备知识
1. 原码
定义
✨原码是一种用二进制表示有符号整数的编码方式。其中最高位表示符号位0为正1为负。其余位是数值位表示数值的绝对值。
举个“栗子”来说 1的原码是001 ;-1的原码是101 ;
✨我们可以看出互为相反数的两个数的原码除了第一位的符号位不一样以外其余位都相同。那么可能有聪明的小伙伴们就想到了0是不是0也有两种表达方式呢果然聪明在原码中0和-0的表示是不一样的。
优缺点
❤️优点简单直观易于理解和计算。缺点加减法运算复杂需要考虑符号位的处理。-0多占了一个数的表达位置导致原码也可表示的总数减少了1个。
✨那可能又有小伙伴要问了一个数很多吗哈哈一个-0单单看起来不多但是一群-0不就多了吗(这就告诉了我们人多力量大的道理一个人可以走得很快但一群人才能走得更远)。另外-0的存在还会带来一些其他的问题比如1️⃣(0)(-0)2️⃣ 0和-0哪个大
怎么一个原码事这么多烦呐下面就让我们来看看更为合适的编码方式–补码。 2. 补码:
❤️计算机中存储数据时通常采用补码编码方式。
定义
✨补码也是一种用于表示有符号整数的编码方式。其中最高位最左侧位是符号位0表示正数1表示负数。其余位是数值位。
对于正数补码就是其二进制原码本身。(看来不讲原码还不能开补码)如数值3的补码就是0011。对于负数补码是其对应正数的原码的各位取反末位加一符号位取1。
如-3的补码可以通过三步得到(因为3的原码是0011) 1️⃣各位取反1100 2️⃣末位加一1101 3️⃣符号位取11101 优缺点 ❤️优点 1️⃣加减法运算可以直接按位运算无需特殊处理符号位。相对原码来说更加方便 2️⃣解决了原码中存在的正零和负零的问题。-0的位置让给了最小的数 3️⃣表示范围更加均衡。补码的最小值的绝对值比最大值的绝对值多1 缺点 1️⃣加减法时可能溢出。 2️⃣对称不明显。看吧上帝为你打开一扇窗的同时也会为你关闭一扇门
当然补码的知识宝库偌大无比我现在只不过是揭开了其冰山一角但对我们解决一般的问题来说足够了。 二、按位取反:
✨将一个数的二进制表达的每一位取反即0变为11变为0。取反符号用 ~ 表示。从最低位最右侧位开始逐位进行取反操作。
例如对于一个8位的二进制数10101010按位取反后的结果是01010101。注意这是补码的取反哦
下面来看几个具体的代码 1️⃣1的按位取反
#includestdio.hint main(void)
{int a 0b1;printf(%d, ~a);return 0;
}猜猜它的输出是多少 输出0是不是哈哈哈是0你就上当了 咦❓为什么❓为什么不是0❓ 1-0 没有问题啊❗️到底是哪里出错了❓会是哪里错了呢❓ 阁下莫慌我们慢慢来解释。
首先a是一个int类型一般是4个字节Byte,而一个字节是8位8个bit,所以总共是32位。0b1是1的二进制表达具体可以写为00000000 00000000 00000000 00000001.下面我们对它进行取反操作得11111111 11111111 11111111 11111110但它是一个补码我们以%d的形式输出就要得到它的十进制表达可以理解为真值那么问题来了补码怎么转换成真值呢考虑到具体的定义过于枯燥乏味所以我直接告诉你转换的方法可以先将补码转换为机器数而计算机中的机器数一般用原码来表示所以问题就转化为了补码-原码。将补码的符号位不变其余各位取反末位加一。这好像和原码转补码有点类似啊也就是10000000 00000000 00000000 000000011--- 10000000 00000000 00000000 00000010再转换成十进制整数就是-2。
2️⃣0的按位取反(%d的形式输出)
#includestdio.hint main(void)
{printf(%d, ~0);return 0;
}2️⃣0的按位取反%u的形式输出
#includestdio.hint main(void)
{printf(%u\n, ~0);printf(%lld, ((long long)1 32) - 1);return 0;
}咦❓为啥同样是0但取反后的输出结果不一样呢
%d:有符号十进制整数的输出 (signed int): -2 ^ 31 -- 2 ^ 31 - 1%u:无符号十进制整数的输出 (unsigned int) : 0 -- 2 ^ 32 - 1
这个有无符号具体就体现在是否有符号位有符号位就少一位数值位没有符号位就都是数值位。
0的补码00000000 00000000 00000000 00000000~0的补码11111111 11111111 11111111 11111111
✨对于有符号整数来说有正有负且第一位是符号位。~0第一位是1所以要转换成原码再输出 即10000000 00000000 00000000 00000001其值为-1 ✨对于无符号整数来说没有符号位32个位都是数值位所以可以直接计算。因此两者输出不同。 三、拓展应用
1. 巧求相反数不用-
✨相反数相必大家都知道1的相反数是-10的相反数是0简单来说一个数的相反数就是再其前面加个-
那么不用这种方法还可以求相反数吗
哈哈其实这个问题我们上面已经说过了直接利用补码的定义求一个数的相反数就是各位取反末位加一。即-x~x1
#includestdio.h
int main(void)
{int x -18;printf(%d的相反数是%d\n,x, ~x 1);int y 18;printf(%d的相反数是%d,y, ~y 1);return 0;
}当然了要注意数据的溢出问题。 2. 代替减法不用-实现减法
✨现给定int类型的两个正数不用-如何实现减法操作 根据减法定义减去一个数就等于加上这个数的相反数 所以a - b a (-b) a (~b 1);
#includestdio.h
int main(void)
{int a1,b2;printf(%d-%d%d\n,a, b,a~b1);return 0;
}3. 代替加法不用实现加法
✨给定两个int类型的正数不用实现加法。根据加法定义加上一个数等于减去一个数的相反数。即a b a - (-b) a - (~b 1)a - ~b - 1;
#includestdio.h
int main(void)
{int a1,b2;printf(%d%d%d\n,a, b,a-(~b 1));return 0;
}好了今天的讲解就到这里了相信你也是收获满满吧 终于肝完了好累