第7天----【位运算进阶之----位或(|)】七夕特别版

❤️今天我们来学习位或
注意:本文中的位是从右往左来说的,也就是从低位开始数的!!!


文章目录

  • 一、昨日重现:
  • 二、基础知识:
  • 三、拓展应用:
    • 1. 设置特定位:
      • 拓展思考:
    • 2. 权限控制:
    • 3. 掩码操作:
    • 4. 位标志:
    • 5.位运算优化:


一、昨日重现:

  • 当然,在正式学习之前,让我们先看看昨天留下的问题:⭐️如何判断一个数是不是2的幂❓

✨要想解决这个问题,我们先要搞清楚,2的幂有什么特征?

2的幂 十进制表达 二进制表达
2^0 1 0001
2^1 2 0010
2^2 4 0100
2^3 8 1000

✨我们简单地列举出几个2的幂的二进制表达,可以发现,只有一位是1(且是首位),其余位全部是0。利用昨天学过的位与(&)知识,全1才1,有0则0,因此,将(2^n) & (2^n-1),结果必定是0,从而得到判断一个数是否是2的幂的方法之一:

if ( (n)&(n-1)==0 )  cout<<"n是2的幂";

二、基础知识:

✨C语言中的位或运算符|是一种按位逻辑运算符,用于对两个操作数每个位执行逻辑或操作。位或操作的结果是两个操作数的每个对应位进行逻辑或运算后的值。

位或运算符的使用方法如下:

result = operand1 | operand2;
  • 其中,operand1operand2是要进行位或运算的两个操作数,result是运算结果。

位或运算的规则如下:

  • (全0才0) 如果两个操作数的对应位都为0,则结果位为0。
  • (有1则1) 如果两个操作数的对应位有一个为1,则结果位为1。

(是不是和逻辑或很像呢❓)
示例如下:

#include 

int main() {
   unsigned int a = 5;  // 二进制表示为 0101
   unsigned int b = 9;  // 二进制表示为 1001
   unsigned int result = a | b;  // 二进制表示为 1101,十进制表示为 13

   printf("result: %u\n", result);

   return 0;
}
  • 在上面的例子中,我们使用了两个无符号整数变量ab,它们的二进制表示分别为01011001。通过对这两个变量进行位或运算,我们得到了结果1101,它的十进制表示为13。

三、拓展应用:

第7天----【位运算进阶之----位或(|)】七夕特别版_第1张图片

1. 设置特定位:

✨可以使用位或运算将某个变量的特定位设置为1,而不影响其他位的值。例如,可以使用位或运算设置标志位、控制位或权限位。

示例如下::

#include 

int main() {
   unsigned int flags = 0;  // 所有位都为0
   unsigned int mask = 1;   // 二进制表示为 0001

   flags = flags | mask;    // 将最低位设置为1

   printf("flags: %u\n", flags);

   return 0;
}
  • 在上面的例子中,我们使用了一个无符号整数变量flags,它的所有位都为0。然后,我们定义了一个二进制表示为0001的掩码mask。通过对flagsmask进行位或运算,我们将flags的最低位设置为1。最终,flags的值变为1。

拓展思考:

❤️怎么将任意二进制的特定位置为1呢?置为0又该怎么做?
解:

  • ✨我们首先来看第一个问题,将任意二进制的特定位置为1
    我这里有两种方法:
    方法一:利用位或的思想
    要将一个二进制数的第n位(从右往左,即从低位开始数)置为1,则只需要将该二进制数与2^(n-1)位或即可。比如对1001来说,要将第三位置为0,只需要将其与100(即4=2 ^(3-1))位或即可。
    方法二:加法
    先将该位置为0,再加上2^(n-1);

  • ✨对于第二个问题,将任意二进制的特定位置为0,解法与第一个问题类似。
    方法一:利用位与的思想
    将该数和111…101…111位与(这个二进制数只有特定位上是0,其余都是1)。比如要将1011第2位置为0,只需将其和1101位与即可。
    方法二:减法
    先将该位置为1,再减去2^(n-1);

❤️怎么将低位连续的0置为1呢?
解:对于11110000来说,要想将低位的4给零都置为1,只需要将其和11101111位或即可。也就是n|(n-1).(这是一种特殊情况)

❤️怎么将低位的第一个零置为1呢?
解:对于11110111来说,要想将低位的第一个0置为1,只需要将其和11111000位或即可。也即n|(n+1).(普遍情况)


2. 权限控制:

✨可以使用位或运算将不同的权限组合在一起。例如,可以使用不同的位代表不同的权限,然后通过位或运算将多个权限合并在一起。

#include 

#define READ_PERMISSION  1   // 二进制表示为 0001
#define WRITE_PERMISSION 2   // 二进制表示为 0010
#define EXECUTE_PERMISSION 4 // 二进制表示为 0100

int main() {
   unsigned int permissions = 0;

   permissions = permissions | READ_PERMISSION;   // 设置读权限
   permissions = permissions | WRITE_PERMISSION;  // 设置写权限

   printf("permissions: %u\n", permissions);

   return 0;
}
  • 在上面的例子中,我们使用了一个无符号整数变量permissions,它的所有位都为0。然后,我们定义了三个不同的权限标志,分别代表读权限、写权限和执行权限。通过对permissions和相应的权限标志进行位或运算,我们将读权限和写权限合并在一起。最终,permissions的值变为3。

3. 掩码操作:

✨可以使用位或运算来创建一个掩码,用于提取或设置特定的位。掩码是一个二进制数,其中每个位对应于要提取或设置的位。通过将掩码与另一个数进行位与或位或运算,可以提取或设置特定的位。(一般是位与)

#include 

#define BIT_MASK 0x0F  // 二进制表示为 00001111

int main() {
   unsigned int value = 0x3A;  // 二进制表示为 00111010

   unsigned int maskedValue = value & BIT_MASK;

   printf("maskedValue: %u\n", maskedValue);

   return 0;
}
  • 在上面的例子中,我们使用了一个无符号整数变量value,它的二进制表示为00111010。然后,我们定义了一个掩码BIT_MASK,它的二进制表示为00001111。通过对value和掩码进行位与运算,我们提取了value的低4位。最终,maskedValue的值变为10。

4. 位标志:

✨可以使用位或运算来创建一个包含多个位标志的变量。每个位标志代表一个特定的状态或属性。通过位或运算将多个位标志合并在一起,可以在一个变量中同时表示多个状态或属性。(和权限控制有点类似)

#include 

#define FLAG_A 1   // 二进制表示为 0001
#define FLAG_B 2   // 二进制表示为 0010
#define FLAG_C 4   // 二进制表示为 0100

int main() {
   unsigned int flags = 0;

   flags = flags | FLAG_A;   // 设置标志A
   flags = flags | FLAG_B;   // 设置标志B

   printf("flags: %u\n", flags);

   return 0;
}
  • 在上面的例子中,我们使用了一个无符号整数变量flags,它的所有位都为0。然后,我们定义了三个不同的标志,分别代表标志A、标志B和标志C。通过对flags和相应的标志进行位或运算,我们将标志A和标志B合并在一起。最终,flags的值变为3。

5.位运算优化:

✨有时,使用位或运算可以优化代码的执行效率。例如,可以使用位或运算来替代一些复杂的逻辑运算,从而减少计算量和执行时间。


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

附一张漂亮的流星雨照片:(许愿.gif)

你可能感兴趣的:(c++,算法,c语言)