【位运算进阶之

您所在的位置:网站首页 字节最高位为 【位运算进阶之

【位运算进阶之

2024-01-29 00:46| 来源: 网络整理| 查看: 265

今天我们来谈谈按位取反这件事。 简单来说,按位取反就是先将一个数写成其二进制表达形式,然后1变0,0变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️⃣符号位取1:1101

优缺点:

❤️优点: 1️⃣加减法运算可以直接按位运算,无需特殊处理符号位。(相对原码来说更加方便) 2️⃣解决了原码中存在的正零和负零的问题。(-0的位置让给了最小的数) 3️⃣表示范围更加均衡。(补码的最小值的绝对值比最大值的绝对值多1)

💔缺点: 1️⃣加减法时可能溢出。 2️⃣对称不明显。(看吧,上帝为你打开一扇窗的同时,也会为你关闭一扇门)

🐒当然,补码的知识宝库偌大无比,我现在只不过是揭开了其冰山一角,但对我们解决一般的问题来说,足够了。

二、按位取反:

✨将一个数的二进制表达的每一位取反,即0变为1,1变为0。取反符号用 "~" 表示。(从最低位(最右侧位)开始,逐位进行取反操作。)

例如,对于一个8位的二进制数10101010,按位取反后的结果是01010101。(注意,这是补码的取反哦)

下面来看几个具体的代码: 1️⃣1的按位取反:

#include int 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 00000001+1---> 10000000 00000000 00000000 00000010,再转换成十进制整数就是-2。

2️⃣0的按位取反:(%d的形式输出)

#include int main(void) { printf("%d", ~0); return 0; }

在这里插入图片描述

2️⃣0的按位取反:(%u的形式输出)

#include int main(void) { printf("%u\n", ~0); printf("%lld", ((long long)1 int a=1,b=2; printf("%d-%d=%d\n",a, b,a+~b+1); return 0; }

在这里插入图片描述

3. 代替加法(不用+实现加法)

✨给定两个int类型的正数,不用+实现加法。根据加法定义,加上一个数等于减去一个数的相反数。即:a + b = a - (-b) = a - (~b +1)=a - ~b - 1;

#include int main(void) { int a=1,b=2; printf("%d+%d=%d\n",a, b,a-(~b + 1)); return 0; }

在这里插入图片描述

好了,今天的讲解就到这里了,相信你也是收获满满吧! 终于肝完了,好累!!!

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3