找到标志枚举长度的有效方法?
考虑一下:
[Flags]
enum Colors
{
Red=1,
Green=2,
Blue=4
}
Colors myColor=Colors.Red|Colors.Blue;
目前,我正在这样做:
int length=myColors.ToString().Split(new char[]{','}).Length;
但我希望有一种更有效的方法来查找长度,也许基于位集操作。
如果可能,请解释您的解决方案的工作原理和原因。
另外,如果这是重复的,请指出它,我将删除这个问题。我能找到的唯一类似的问题是关于查找 Colors
枚举的所有可能组合的长度,而不是 myColors
变量的长度。
更新:我仔细对每个解决方案进行了基准测试(每个解决方案 1 000 000 次迭代),结果如下:
- Stevo3000 - 8ms
- MattEvans - 10ms
- Silky - 34ms
- Luke - 1757ms
- Guffa - 4226ms
- Tomas Levesque - 32810ms
Stevo3000 是明显的赢家(Matt Evans 持有)银牌)。
非常感谢您的帮助。
更新2: 该解决方案运行速度更快:100 000 000 次迭代仅需 41 毫秒(比 Stevo3000 快大约 40 倍(32 位操作系统))
UInt32 v = (UInt32)co;
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
UInt32 count = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
Consider this:
[Flags]
enum Colors
{
Red=1,
Green=2,
Blue=4
}
Colors myColor=Colors.Red|Colors.Blue;
Currently, I'm doing it as follows:
int length=myColors.ToString().Split(new char[]{','}).Length;
But I hope there is a more efficient way of finding the length, maybe based on bitset operations.
Please, if possible, provide explanation why and how your solution works.
Also, if this a duplicate, please point to it and I'll delete this question. The only similar questions on SO I've been able to find were concerned about finding the length of all possible combinations of Colors
enum, but not of the myColors
variable.
UPDATE: I carefully benchmarked every solution (1 000 000 iterations each) and here is the results:
- Stevo3000 - 8ms
- MattEvans - 10ms
- Silky - 34ms
- Luke - 1757ms
- Guffa - 4226ms
- Tomas Levesque - 32810ms
The Stevo3000 is a clear winner (with Matt Evans holding silver medal).
Thank you very much for your help.
UPDATE 2:
This solution runs even faster: 41 ms for 100 000 000 iterations (roughly 40 times faster (32bit OS) than Stevo3000)
UInt32 v = (UInt32)co;
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
UInt32 count = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
以下代码将为您提供为大小从字节到长的任何类型的给定数量设置的位数。
该代码非常高效,因为它只对每个位迭代一次,而不是像其他示例中那样对每个可能的位迭代一次。
The following code will give you the number of bits that are set for a given number of any type varying in size from byte up to long.
This code is very efficient as it only iterates once for each bit rather than once for every possible bit as in the other examples.
以下是一些操作
Flags
枚举的扩展方法:在您的情况下,您可以使用
GetFlags
方法:它可能不如 Luke 的答案那么有效,但它更容易使用。 ..
Here are a few extension methods to manipulate
Flags
enumerations :In your case you can use the
GetFlags
method :It's probably not as efficient as Luke's answer, but it's easier to use...
这是我对此的看法...它计算值中设置的位数
Here's my take on this... it counts the number of set bits in the value
这是一种计算位数的相当简单的方法。每个位依次移位到
Int64
的 LSB,该 LSB 与 1 进行AND
运算(以屏蔽任何其他位),然后添加到运行中全部的。Here's a reasonably easy way of counting the bits. Each bit is shifted in-turn to the LSB of an
Int64
which isAND
-ed with 1 (to mask out any of the other bits) and then added to the running total.粗略的近似值只是计算
myColors
中设置的位数,但这仅在每个枚举成员的值都是 2 的幂时才有效。A rough approximation will be just counting the number of bits set in
myColors
, but that will only work if every enumeration members' value is power of 2.假设它们是标志,您可以使用此处的方法之一,计算设置的位数。
它之所以有效,是因为只要它们是标志,当每个标志被“或”时,它就会设置一位。
--
使用该链接上的方法之一编辑示例代码:
Assuming they are flags, you can just use one of the methods here, to count the number of bits set.
It works because, as long as they are flags, when each one is 'OR'd' on, it sets one bit.
-- Edit
Sample code using one of the methods on that link:
我为自己制定了一个辅助方法。也许对其他人有用。
I've made a helper method for myself. Maybe it'll be useful for others.
最可靠的解决方案是测试枚举中的每个值:
即使该值在枚举中没有定义值的情况下设置了位,这也将起作用,例如:
这也适用于具有使用更多值的值的枚举比一位:
The solution that is most reliable is to test for each value in the enumeration:
This will work even if the value has bits set where there are no defined value in the enumeration, for example:
This will also work for enumerations with values that use more than a single bit:
试试这个……
还是这太明显了?
编辑:
好的,我刚刚再次阅读了这个问题,并意识到您需要“mycolors”的长度,而不是“Colors”的长度 - 让我考虑一下。
进一步编辑:
现在我很困惑 - OP 发布的解决方案永远不会工作,因为 myColor.ToString() 返回 '5' 并将 Split(new char[]{','}) 应用于此将导致一个带有长度为1。
OP真的让它发挥作用了吗?
Try this...
...or is that too obvious?
EDIT:
OK, I just read the question again, and realised that you need the length of 'mycolors', not 'Colors' - let me think about that.
FURTHER EDIT:
Now I'm confused - the OP's posted solution would never work, as myColor.ToString() returns '5' and applying Split(new char[]{','}) to this would result in a array with a length of 1.
Did the OP actually get this to work?