Redis二进制反转算法分析
Posted evenleo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis二进制反转算法分析相关的知识,希望对你有一定的参考价值。
在 redis 源码中 dictScan 算法中用到了用到了非常经典的二进制反转算法,该算法对二进制的反转高效而实用,同时对于理解位运算也有非常大的帮助。先呈现源码:
/* Function to reverse bits. Algorithm from: * http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */ static unsigned long rev(unsigned long v) { unsigned long s = 8 * sizeof(v); // bit size; must be power of 2, 此处为32 unsigned long mask = ~0; //11111111111111111111111111111111 while ((s >>= 1) > 0) { //循环5次 mask ^= (mask << s); // 取得想要局部对换的掩码 // 左移s位并保留低位,右移s位并保留高位,然后两部分或运算 // 这里是实现移位的精华所在,结合下面打印信息有助于理解 v = ((v >> s) & mask) | ((v << s) & ~mask); } return v; }
源码的总体思路是:用迭代的思想将32位的二进制数先将前16位和后16位对换,然后将前16位二进制数的前8位和后8位对换,后16位类似,再讲前8位的二进制数的前4位和后4位对换。。。最终实现整个二进制的反转。当然这里的实现过程非常巧妙,这也是位运算神秘而神奇的特点,理解这个过程,对于理解计算机的原理都有很大的帮助。
但上面的描述得还是比较抽象,还不足以帮助理解上面的算法实现,下面来对算法的实现过程加一些打印,以便更好的理解算法的实现原理。
#include <iostream> using namespace std; // 打印二进制 void printBits(const unsigned long v) { unsigned long mask = 1 << 31; while ((mask) > 0) { int bit = (v & mask) ? 1 : 0; cout << bit; mask >>= 1; } cout << endl; } static unsigned long rev_test(unsigned long v) { unsigned long s = 8 * sizeof(v); // bit size; must be power of 2 unsigned long mask = ~0; cout << "s : "; printBits(s); cout << "mask : "; printBits(mask); while ((s >>= 1) > 0) { cout << endl; cout << "s : "; printBits(s); cout << "mask : "; printBits(mask); cout << "mask<<s: "; printBits(mask << s); mask ^= (mask << s); cout << "mask^= : "; printBits(mask); v = ((v >> s) & mask) | ((v << s) & ~mask); cout << "v : "; printBits(v); } return v; } int main() { unsigned long v = 8; cout << "v : "; printBits(v); cout << endl; v = rev_test(v); cout << endl; cout << "v : "; printBits(v); cout << endl << endl << endl; system("pause"); return 0; }
运行上述程序结果如下:
以上是关于Redis二进制反转算法分析的主要内容,如果未能解决你的问题,请参考以下文章
使用 C++ 反转句子中的每个单词需要对我的代码片段进行代码优化
2021-09-11:给你一个32位的有符号整数x,返回将x中的数字部分反转后的结果。反转后整数超过 32 位的有符号整数的范围就返回0,假设环境不允许存储 64 位整数(有符号或无符号)。(代码片段