有人可以解释二进制数是如何被逆转的。
unsigned rev = 0;
unsigned k = n;
while (k)
{
// add rightmost bit to rev
rev = (rev << 1) | (k & 1);
k = k >> 1; // drop last bit
cout<<"k val is "<<bitset<8>(k)<<endl;
cout<<"rev val is "<<{bitset<8>(rev)<<endl;
}
如果n = 9,则输出
k val是00000100
rev val是00000001
k val是00000010
rev val是00000010
k val是00000001
rev val是00000100
k val是00000000
rev val是00001001
9是Palindrome
我在这里提到问题2:http://www.techiedelight.com/bit-hacks-part-6-random-problems/
据我所知,如果“|”为真,则只执行第一个表达式条件声明。所以,这里rev&lt;&lt; 1只对第一次执行循环而言是假的,而对于休息则不是。因此,对于最后一个条件,rev最终如何获得1,因为(k&amp; 1)将不会被执行。只有左移才能执行吗?
答案 0 :(得分:0)
变量rev
初始化为0
,它将包含结果。 while
循环迭代,而k
是输入,剩下任何设置位。循环体的第一个语句屏蔽k
的最后一位并将其复制rev
,它在过程中向左移一位(由移位运算符)。在循环迭代中,输入和输出都被移位 - 输入向右移动,输出移到左边。
答案 1 :(得分:0)
可能有用的一个可视化是堆栈:假设您的数字n
由一堆二进制数字表示,最低有效数字位于堆栈顶部。
用于位反转的常用算法是从n
堆栈中逐个迭代地弹出数字并将它们堆叠在另一个堆栈中(在您的情况下代表rev
)。
k = k >> 1;
从堆栈n
中弹出一个二进制数字(在您的代码中重命名为k
)
rev = (rev << 1) | (k & 1);
将二进制数字堆叠在k
堆栈的顶部。
在代码中,弹出/堆栈操作被反转以避免临时。
最后,只要n
堆栈中有数字,就应该重复执行pop / stack的操作。这是因为while
条件仅为k
,它会测试k
是否为0(没有数字)。
PS:您有一些低级算法可以在Bit Twiddling Hacks website上执行位反转。算法以性能为目标,因此可能不易理解。