C++之——位运算

一般情况下学习位运算就学习了进制转换原码反码补码,位运算的运用讲的少一些,自己补充一下

正数的原码补码反码是一样的

负数的反码是除了第一位符号位不动,其他位置全部取反得到的

负数的补码是在反码的基础上加一实现的,负数是按照补码的形式参加位运算的。

二八十十六进制转换就不赘述

小数用二进制如何表示?

1、整数部分转为二进制,取出小数部分

2、用小数乘以2,得到一个数,整数部分取出来作为小数二进制表示的第一位

3、再用其中的小数乘以2,以此类推

tip:有些时候小数部分会出现无限循环,会导致结果出现误差

eg:3.14
0.14*2 = 0.28 ———————— 0
0.28*2 = 0.56 ———————— 0
0.56*2 = 1.12 ———————— 1
0.12*2 = 0.24 ———————— 0
0.24*2 = 0.48 ———————— 0
0.48*2 = 0.96 ———————— 0
0.96*2 = 1.92 ———————— 1
。。。。。。。

所以3.14用二进制表示就是11.0010001111......

应用

1. 按位与
1.1 判断奇偶

    int x = 100;
    int y = 1;
    std::cout << x << (x & y ? " is odd" : " is even") << std::endl;


1.2 取指定位数的值
上面的情况可以看作是取x最后一位的值,根据最后一位是0还是1来判断奇偶,更一般的我们可以通过控制y来提取不同位置的值。

    int x = 0b111011;
    int y = 0b1111;
    std::cout << bitset<sizeof(int) * 8>(x & y) << std::endl;	// 00000000000000000000000000001011


1.3 判断2的整数幂

 	int x = 64;
    int y = x - 1;
    std::cout << ((x & y) ? "no" : "yes") << std::endl; // yes


1.4 二进制数中1的个数(汉明权重问题)
可以参考 C语言-统计二进制数中1的个数-Hamming weight-汉明权重问题。

2. 按位或
这个有一个比较经典的应用,比如对于一些标志位的表达。比如对于一张图片可能是彩色,可能是灰度图,图像的深度可能是8位,或者32位(当然还有其他,这里仅仅举例)。

数值       意义
x0          灰度图
x1          彩色图
0x          8位
1x          32位
比如00 表示8位灰度图。这里就是通过按位或来计算。

 	int x = 0b00;	// 灰度图
    int y = 0b10;	// 32位
    int a = x | y;
    switch(a){
    	case 0:
    		std::cout << "8 bits gray image";
    		break;
    	case 1:
    		std::cout << "8 bits color image";
    		break;
    	case 2:
    		std::cout << "32 bits gray image";
    		break;
    	case 3:
    		std::cout << "32 bits color image";
    		break;
    	default:
    		break;
    }


3. 取反
3.1 正负数变换
比如100变-100,可能有人觉得不就是加个符号,或者乘-1就可以了么,但是想想底层的实现呢?

	int x = 100;
    int y = (~x) + 1;
    std::cout << y << std::endl;


当然借助这个操作,其实可以进一步拓展来求取绝对值。只需要先对符号位进行判断,如果是负数(符号位为1)则执行上面的代码变为正数即可。

3.2 圆整到某个数的整数倍
在深度学习的图像预处理中可能会遇到需要将图像的尺寸圆整到网络步长(比如32)的整数倍的问题。这里可以借助取反和与操作实现。

#define ALIGN(num, align) (((num) + (align)-1) & ~((align)-1))

int size = ALIGN(240, 64);
std::cout << size << std::endl;	//256


4. 异或
4.1 交换两个数字
不借助第三个变量,交换两个变量的值,这是一个经典的题,解法比较多,其中一种就是借助异或操作。

   

	int x = 100;
    int y = 20;
    if (x != y)  
    {  
        x ^= y;  
        y ^= x;  
        x ^= y;  
    }  
    std::cout << "x is " << x << ", y is " << y << std::endl;


4.2 加密
根据异或操作的性质,可以用于加密。比如设置一个 key,对于一段二进制信息 msg,msg 与 key 异或就完成了加密,而再进行一次异或操作就完成了解密。

5. 左移
在符号位不为1的情况下,左移相当于乘2。

5.1 二进制数高低位互换

    int x = 0b1010110100111111;
    int y = (x << 8) | (x >> 8);
    std::cout << bitset<sizeof(int) * 8> (y) << std::endl;


6. 右移
对无符号数,右移时左边高位移入0;对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0。
如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。移入0的称为“逻辑移位”,即简单移位;移入1的称为“算术移位”。

C语言-统计二进制数中1的个数-Hamming weight-汉明权重问题 中的”神人法“便是借助移位实现的。

仅为学习记录,不存在其他关系,很多题的小步骤都在里面,望采纳

参考
C++:位操作基础篇之位操作全面总结

C++ 算法篇 位运算
————————————————
版权声明:本文为CSDN博主「kuweicai」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kuweicai/article/details/117488071

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值