给定一个无符号的int,获得设置位的"索引"的最快方法是什么?
所以例如0110设置了位1和2,1000设置了位3 1111设置了位0,1,2,3
解决方案
回答
我将其下移并在循环中测试最低有效位。使用32位掩码(或者unsigned int的长度)可以更快地进行测试。
/艾伦
回答
for( int i = 0; variable ; ++i, variable >>= 1 ) { if( variable & 1 ) // store bit index - i }
回答
最快取决于意思。
如果意思是"编写简单代码",则在.NET中,我们可以使用BitArray类,并将每个位引用为布尔值true / false。
BitArray类
回答
如果实际上只有4位,那么最快的方法肯定会涉及查找表。毕竟只有16种不同的可能性。
回答
@艾伦·温德...
不需要额外的移位。不进行位移位会更有效,因为比较最低有效位与比较第二最低有效位一样有效,依此类推。进行位移位也只是使所需的位操作加倍。
firstbit = (x & 0x00000001) secondbit = (x & 0x00000002) thirdbit = (x & 0x00000004) //<-- I'm not saying to store these values, just giving an example. ...
无论如何,x86系统上的所有操作都是由32位寄存器完成的,因此单位比较将与32位比较一样有效。
更不用说拥有循环本身的开销了。
这个问题可以用固定数量的代码行来完成,并且无论代码是在x86还是x64上运行,我所描述的方式都更加有效。
回答
Internet上所有这些小技巧和小技巧的最佳参考
回答
我们可以采用迭代int字节的混合方法,使用查找表确定每个字节中的设置位的索引(分解为半字节)。然后,我们需要向索引添加偏移量以反映其在整数中的位置。
即假设我们从32位int的MSB开始。高位半字节索引我将称为upper_idxs,低位半字节索引我将称为lower_idxs。然后,我们需要将24个元素添加到lower_idxs的每个元素中,并将28个元素添加到upper_idxs的每个元素中。下一个字节将被类似地处理,只是偏移量分别为16和20,因为该字节为8位"向下"。
在我看来,这种方法是合理的,但我很乐意证明自己是错误的:-)
回答
如果它是.NET,并且我们不得不经常使用它,那么我希望它提供一个流畅的界面。
我将创建以下类(对BitTools的名称并不完全满意)。
[Flags] public enum Int32Bits { // Lookup table but nicer None = 0, Bit1 = 1, Bit2 = 1 << 1, Bit3 = 1 << 2, Bit4 = 1 << 3, Bit5 = 1 << 4, Bit6 = 1 << 5, Bit7 = 1 << 6, Bit8 = 1 << 7, Bit9 = 1 << 8, Bit10 = 1 << 9, Bit11 = 1 << 10, Bit12 = 1 << 11, Bit13 = 1 << 12, Bit14 = 1 << 13, Bit15 = 1 << 14, Bit16 = 1 << 15, Bit17 = 1 << 16, Bit18 = 1 << 17, Bit19 = 1 << 18, Bit20 = 1 << 19, Bit21 = 1 << 20, Bit22 = 1 << 21, Bit23 = 1 << 22, Bit24 = 1 << 23, Bit25 = 1 << 24, Bit26 = 1 << 25, Bit27 = 1 << 26, Bit28 = 1 << 27, Bit29 = 1 << 28, Bit30 = 1 << 29, Bit31 = 1 << 30, Bit32 = 1 << 31, } public static class BitTools { public static Boolean IsSet(Int32 value, Int32Bits bitToCheck) { return ((Int32Bits)value & bitToCheck) == bitToCheck; } public static Boolean IsSet(UInt32 value, Int32Bits bitToCheck) { return ((Int32Bits)value & bitToCheck) == bitToCheck; } public static Boolean IsBitSet(this Int32 value, Int32Bits bitToCheck) { return ((Int32Bits)value & bitToCheck) == bitToCheck; } public static Boolean IsBitSet(this UInt32 value, Int32Bits bitToCheck) { return ((Int32Bits)value & bitToCheck) == bitToCheck; } }
我们可以通过以下方式使用它:
static void Main(string[] args) { UInt32 testValue = 5557; //1010110110101; if (BitTools.IsSet(testValue, Int32Bits.Bit1)) { Console.WriteLine("The first bit is set!"); } if (testValue.IsBitSet(Int32Bits.Bit5)) { Console.WriteLine("The fifth bit is set!"); } if (!testValue.IsBitSet(Int32Bits.Bit2)) { Console.WriteLine("The second bit is NOT set!"); } }
对于每个(U)Int大小,我们可以创建另一个Int * Bits枚举以及IsSet和IsBitSet的正确重载。
编辑:我读错了,你说的是无符号整数,但是在这种情况下是一样的。
回答
两步:
- 用
set_bit = x&-x;提取每个设置位。 x&= x-1;
- 减去1并设置计数位。
回答
我认为这会有所帮助
import java.util.*; public class bitSet { public static void main(String[]args) { Scanner scnr = new Scanner(System.in); int x = scnr.nextInt(); int i = 0; while (i<32) { if ( ((x>>i)&1) == 1) { System.out.println(i); } i++; } } }