Bitwise operator in C/C++

歡迎來到二進位的世界。電腦資料都是以二進位儲存,想當然程式語言的變數也都是以二進位儲存。在 C/C++ 當中有幾個位元運算子: << SHIFT LEFT 、 >> SHIFT RIGHT 、 & AND 、 | OR 、 ^ XOR 、 ~ NOT ,可以對變數進行位元運算。接下來要介紹位元運算的一些用途。

<< SHIFT LEFT
>> SHIFT RIGHT

這兩個運算子的功能主要是移動一個變數中的所有位元,位元向左 / 向右移動之後,最高位 / 最低位的位元會消失,最低位 / 最高位的位元補 0 :

5 << 1 = 10 // 00101 的全部位元向左移動一位數變成 01010。
5 << 2 = 20 // 00101 的全部位元向左移動兩位數變成 10100。
5 >> 1 = 2  // 00101 的全部位元向右移動一位數變成 00010。
5 >> 2 = 1  // 00101 的全部位元向右移動一位數變成 00001。

在十進位當中,當全部位數向左移動一位時,數值大小會變成原來的十倍,向左移動兩位時,會變成原來的百倍。這種情形在二進位也是成立的,當全部位元向左移動一位時,會變成原來的兩倍,向左移動兩位時,會變成原來的四倍。至於往右移動也是類似道理,變成了除法而已。

由於電腦進行位元運算比乘法、除法運算快上許多,所以有很多專業的程式設計師,會利用位元運算來取代乘法、除法運算。優點是程式執行效率增加,缺點是程式碼可讀性變低:

int n = 5;
n = n >> 1; // 即是 n = n / 2 之意。
/* 該式子也可寫成 n >>= 1 或 n /= 2。 */

& AND

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
& 的功能是將兩個變數對應的位元進行 AND 邏輯運算,然後產生新變數。

   00000000000000000000000001110100 -> 116& 00000000000000000000000000101001 -> 41----------------------------------00000000000000000000000000100000 -> 32

& 的特色,就是可以判斷出位元是不是 1 。例如我們想要數一個變數有幾個位元是 1 :

int count_bit_1(int n)
{// 由右往左看n的每一個位元。int c = 0;for (int i=0; i<32; ++i)    // int變數有32個位元if (n & (1 << i))c++;return c;
}int count_bit_1(int n)
{// 一樣是由右往左,但是每次都刪掉n的最左邊位元。int c = 0;for (; n; n>>=1)if (n & 1)c++;return c;
}

| OR

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
| 的功能是將兩個變數對應的位元進行 OR 邏輯運算,然後產生新變數。

   00000000000000000000000001110100 -> 116| 00000000000000000000000000101001 -> 41----------------------------------00000000000000000000000001111101 -> 125
| 的特色,就是把位元強制標記成 1 。例如我們想要把五位數標成 1 :
int mark_5th_bit(int n)
{return n | (1 << 4);
}

^ XOR

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
^ 的功能是將兩個變數對應的位元進行 XOR 邏輯運算,然後產生新變數。

   00000000000000000000000001110100 -> 116^ 00000000000000000000000000101001 -> 41----------------------------------00000000000000000000000001011101 -> 93
^ 的特色,就是把位元的 0 和 1 顛倒。例如我們想要顛倒第五位數:
int reverse_5th_bit(int n)
{return n ^ (1 << 4);
}

~ NOT

~ 0 = 1
~ 1 = 0
~ 的功能是顛倒一個變數每一個位元的 0 和 1 。

 ~ 00000000000000000000000000000011 -> 3----------------------------------11111111111111111111111111111100 -> -4

Bitwise Trick
交換兩個 int 變數

void swap(int& x, int& y)
{x = x ^ y;y = x ^ y;x = x ^ y;
}void swap(int& x, int& y)
{x ^= y ^= x ^= y;
}

判斷一個整數是不是 2 的次方

bool ispow2(int n)
{return (n & -n) == n;
}

整數加一與減一

// 注意:比直接加一和減一還要慢。
void add_one(int& x)
{return -~x; // ++x
}void sub_one(int& x)
{return ~-x; // --x
}

整數變號

void negative(int& x)
{return ~x + 1;          // -x;
}void negative(int& x)
{return (x ^ -1) + 1;    // -x;
}

判斷一整數是偶數還是奇數

// 若回傳true則為偶數,false則為奇數
bool even_or_odd(int& x)
{return x & 1;   // x % 2;
}

非負整數取模數,模數是二的冪次方。

int mod(int& x, int& m) // m是二的冪次方
{return x & (m - 1); // x % m;
}

整數取絕對值

int abs(int& x)
{// x < 0 ? -x : x;return (x ^ (x >> 31)) - (x >> 31);
}

平方根倒數

3D 繪圖經常用到的一個運算,原理是牛頓法。

http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf

Fast Inverse Square Root
// 1.0 / sqrt(x)
float InvSqrt(float x)
{float xhalf = 0.5f*x;int i = *(int*)&x;i = 0x5f3759df - (i>>1);x = *(float*)&i;x = x*(1.5f-xhalf*x*x);return x;
}

計算 32 位元整數有幾個位元是 1

void count_bits(int& x)
{x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1);x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2);x = (x & 0x0f0f0f0f) + ((x & 0xf0f0f0f0) >> 4);x = (x & 0x00ff00ff) + ((x & 0xff00ff00) >> 8);x = (x & 0x0000ffff) + ((x & 0xffff0000) >> 16);
}

顛倒 32 位元整數的位元順序

void reverse_bits(int& x)
{x = ((x >> 1) & 0x55555555) | ((x << 1) & 0xaaaaaaaa);x = ((x >> 2) & 0x33333333) | ((x << 2) & 0xcccccccc);x = ((x >> 4) & 0x0f0f0f0f) | ((x << 4) & 0xf0f0f0f0);x = ((x >> 8) & 0x00ff00ff) | ((x << 8) & 0xff00ff00);x = ((x >> 16) & 0x0000ffff) | ((x << 16) & 0xffff0000);
}

32 位元整數的最高位位元位置

原理是 Binary Search 。

void highest_bit_position(int x)
{x--;x |= x >> 1;x |= x >> 2;x |= x >> 4;x |= x >> 8;x |= x >> 16;x++;return x;
}

Bitwise Operation相关推荐

  1. Bitwise Operation Explained

    原文链接:Bitwise Operation Explained 1.统计一个数置位为1的个数 #include <stdio.h> int __numOf_SET_Bits(int va ...

  2. 位运算::Bitwise operation

    最近学习做cf,第一题永远都是该死的Bitwise operation,好好学习了一下位运算的知识. NOT: The bitwise NOT, or bitwise complement, is a ...

  3. 《Kotlin极简教程》第三章 Kotlin基本数据类型

    正式上架:<Kotlin极简教程>Official on shelves: Kotlin Programming minimalist tutorial 京东JD:https://item ...

  4. 一文详解基于先验地图的视觉定位

    作者丨cc.fy@知乎 来源丨https://zhuanlan.zhihu.com/p/460001686 编辑丨3D视觉工坊 问题定义 给定一份高精度地图或环境模型,给定相机(不限于单目,双目,多目 ...

  5. 一个数字可以在不损失精度的情况下达到的JavaScript的最高整数值是多少?

    这是由语言定义的吗? 是否有定义的最大值? 在不同的浏览器中是否有所不同? #1楼 您要用于按位运算的任何值都必须在0x80000000(-2147483648或-2 ^ 31)和0x7fffffff ...

  6. 系统要关闭,可我程序还有事要处理?

    系统要关闭,可我程序还有事要处理? 问题1描述: 运行了一个客户端程序,服务端表明客户端在线,突然运行客户端程序的电脑关机了,但服务端并不知道客户端下线了,服务端的状态并不能及时更新为下线. 解决方法 ...

  7. 超全总结:神经网络加速之量化模型 | 附带代码

    作者丨郝泽宇 学校丨西安交通大学人机所硕士生 研究方向丨深度神经网络压缩 鸣谢 | XJTU @魏亚东 I.C. @董豪 量化模型(Quantized Model)是一种模型加速(Model Acce ...

  8. TensorRT(4)-Profiling and 16-bit Inference

    前面几节以 LeNet 为例主要介绍了 tensorRT 的简单使用流程.包括,使用 tensorRT 的 NvCaffeParser 工具以及底层 C++ API 来 模型 caffe 解析,构建 ...

  9. 【Findbugs】Findbugs使用指南

    一.简介 Findbugs是一个静态分析工具,它检查类或者jar文件,将字节码与一组缺陷模式进行对比以发现可能的问题.利用这个工具可以在不实际运行程序的情况下对软件进行分析.可以帮助改进代码质量.Fi ...

最新文章

  1. [DNS] 网页无法打开,设置合适的DNS解决问题
  2. MATLAB实战系列(十二)-如何用人工鱼群算法解决带时间窗车辆路径(CVRP)问题(附MATLAB代码)
  3. 华为防火墙USG多出口网络场景是如何排除故障的
  4. TensorFlow2-高阶操作
  5. 垃圾回收②---相关概念
  6. CentOS7 防火墙规则 (firewalld)
  7. tkinter 弹出窗口 传值回到 主窗口
  8. 综合支撑【恶灵附身 Psycho Break】的世界观的概念艺术
  9. java计算机毕业设计家教到家平台源码+mysql数据库+系统+lw文档+部署
  10. 象棋军师app已经上线
  11. 8086汇编基础 8080,8088,8086,80286,80386的地址线,数据线宽度
  12. C语言实现FTP客户端(已编译,亲试可用~)
  13. 最基本财务基础知识,财务知识基础
  14. 小网站云服务器配置推荐,小网站云服务器配置推荐
  15. 【C语言编程】如何整蛊你的损友,让他的电脑一直关机?
  16. 英语单词:through; fall through; write through
  17. libreoffice linux命令行,linux下使用libreoffice 命令行转化进行excel转PDF的排版问题
  18. 烙铁头不沾锡原因分析,及烙铁头保养!
  19. java doc转换docx_java PDF转DOC.docx
  20. 厄米多项式(Hermite Polynomials)

热门文章

  1. H5+在浏览器中打开相机扫描二维码
  2. eNSP配置Martini方式VPLS
  3. 零知识证明java实现
  4. 流量偷跑,运营商该不该赔偿?
  5. 校园网服务器系统方案设计,校园网服务器系统项目设计方案.pdf
  6. 【量化】验证《股市操盘宝典》对周期论
  7. press ESC in 1 seconds to skip startup.nsh,any other key to continue
  8. 用gauss消去法解线性方程组(数值数学实验教程P74ex5.2)-2021-11-03
  9. 在excel中如何筛选重复数据_Excel如何快速筛选
  10. CSS 成长之路(六)顶线、中线、基线、底线与行距