Algorithm 求一个数的位的倒数的最快方法是什么?

Algorithm 求一个数的位的倒数的最快方法是什么?,algorithm,Algorithm,给定一个整数,n。倒数的最快方法是什么?例如,如果n=5 101,则输出应为2010。前缀0不被视为反向。这个问题的独特之处在于,我们不考虑前缀0。 我的做法: 更多输入/输出示例: Input: 7, Output: 0 Input: 8, Output: 7 Input: 10, Output: 5 Input: 98, Output: 29 正如你所看到的,我的方法看起来很幼稚或者效率很低。有没有更好的方法,通过使用一些位操作或任何其他方式更快地获得所需的输出 注意:n也可以是负数!对于

给定一个整数,n。倒数的最快方法是什么?例如,如果n=5 101,则输出应为2010。前缀0不被视为反向。这个问题的独特之处在于,我们不考虑前缀0。

我的做法:

更多输入/输出示例:

Input: 7, Output: 0
Input: 8, Output: 7
Input: 10, Output: 5
Input: 98, Output: 29
正如你所看到的,我的方法看起来很幼稚或者效率很低。有没有更好的方法,通过使用一些位操作或任何其他方式更快地获得所需的输出

注意:n也可以是负数!对于负数,在反转位时必须考虑2的补充

我不是要确切的密码。伪代码或方法将很有帮助

unsigned reversed = 0;
while (num := 0) {
  reversed = reversed << 1;
  reversed |= (num & 1);
  num = num >> 1;
}

将低阶位从原始位移出,然后在反转中将其依次移入高位

这一问题与按位异或指令的开销有关,并与n向上舍入到形式为2^k-1的最小数的问题有关。对于32位int n,您可以将其中一种标准Bithack用于后者:

m = n;
m |= m >> 1;
m |= m >> 2;
m |= m >> 4;
m |= m >> 8;
m |= m >> 16;
return m ^ n;

如果性能真的很重要,可以将其制成表格

逐字节处理从MSB到LSB的整数。如果字节为空,则跳过。否则,使用一个预计算的查找表,其中包含256个前缀项,对于以下字节,使用XOR

if (B[0]) { B[0]= LUT[B[0]]; B[1]^= 255; B[2]^= 255; B[3]^= 255; }
else if (B[1]) { B[1]= LUT[B[1]]; B[2]^= 255; B[3]^= 255; }
else if (B[2]) { B[2]= LUT[B[2]]; B[3]=^255; }
else B[3]= LUT[B[3]];
您还可以使用适当的掩码,一次性对32位进行异或运算。

n没有给出预期结果的原因是数字中的所有前导零。要在将这些零反转为1后屏蔽这些零,最简单的方法是:

m = abs(n);
result = ~m & (int)(exp2(ceil(log2(m)))-1);
这将通过获取正输入的base-2对数来生成正确长度的掩码。n是2的幂的边界情况是正确的,因为结果中的前导1始终为0,因此它从掩码中排除并不重要


性能可能是公平的,但编码是简洁的。

flipn=2^ceilinglgn-1-n,其中lg是log base 2


如果您知道n的最大设置位,那么您可以通过获得最大设置位并将1向左再移动一次,快速获得2^ceilinglgn

@IVlad~n不起作用。。我在C单元n=98中试过;Console.WriteLine~n//输出4294967197,输出不是29。可能它会对有符号位起作用:|可能的重复必须指定如何处理负数,我们无法读懂你的心思。它基本上应该做同样的事情。如果数字是负数,那么它应该是2的补码位。符号位呢???0前缀呢?不工作。将其编码为c,对于输入7,其输出为14。这是出乎意料的:|这似乎是反转数字的位字符串,而不是反转位,这是问题的目的,除非我弄错了。这是个好把戏。但是我真的需要完成所有这些步骤才能达到2^k-1吗?还有,关于负数,这个技巧有效吗?@Abhishek如果你想处理整个32位范围,那么是的。@Abhishek你想对负数做什么?什么都没有。你的把戏对他们也有用。我试着用2的负数补码表示法。谢谢什么是B和LUT?B是字节B[0]假定的MSB,适用于小端,LUT是查找表。查找表是什么样子的?我了解查找表。我想知道,如何为当前问题生成它?好的。知道了。将尝试并返回:那么,2^ceilinglgn是否提供最大设置位?@Abhishek如果n是2的幂,它将为您提供最大设置位;否则,由于天花板功能,它将为您提供下一个更高的位。例如,二进制中的lg4=2,lg8=3,所以ceillg5=ceillg6=ceillg7=ceillg8=3,2^3=8=1000。如果n是2的幂,通过最大设置位得到2^ceilinglgn,则不移位,只使用2^ceilinglgn=2^lgn=n。例如,如果n=8,则n在二进制中为1000,并且n-1=7=111,如所需。如果n为8,则2^ceilinglgn为8。现在,flip8=8-1-8=-1。但预期结果是7。如何处理这种情况?比特旋转黑客页面有两种算法来查找Olgk操作中的最大集合比特,其中k是n的比特数,包括前导零。其余的时间不变。
m = abs(n);
result = ~m & (int)(exp2(ceil(log2(m)))-1);