我相信必须有一个更好的方法来做到这一点.我正在尝试对Flags枚举进行计数操作.在我尝试所有可能的值并计算成功的AND操作之前.
例如
[Flags]
public enum Skills
{
None = 0,
Skill1 = 1,
Skill2 = 2,
Skill3 = 4,
Skill4 = 8,
Skill5 = 16,
Skill6 = 32,
Skill7 = 64,
Skill8 = 128
}
public static int Count(Skills skillsToCount)
{
Skills skill;
for (int i = 0; i < SkillSet.AllSkills.Count; i++)
{
skill = SkillSet.AllSkills[i];
if ((skillsToCount & skill) == skill && skill != Skills.None)
count++;
}
return count;
}
Run Code Online (Sandbox Code Playgroud)
我确信必须有更好的方法来做到这一点,但必须患有精神障碍.谁能建议更好的解决方案?
ste*_*ell 28
下面的代码将为您提供为给定数量的任何类型设置的位数,其大小从byte到long不等.
public static int GetSetBitCount(long lValue)
{
int iCount = 0;
//Loop the value while there are still bits
while (lValue != 0)
{
//Remove the end bit
lValue = lValue & (lValue - 1);
//Increment the count
iCount++;
}
//Return the count
return iCount;
}
Run Code Online (Sandbox Code Playgroud)
这段代码非常有效,因为它只针对每个位迭代一次,而不是像其他示例那样针对每个可能的位迭代一次.
在查看网站后,Assaf建议我设法找到一个稍微不同的解决方案,我为Int32工作.
这是其他任何人的代码:
internal static UInt32 Count(this Skills skills)
{
UInt32 v = (UInt32)skills;
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
UInt32 c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
return c;
}
Run Code Online (Sandbox Code Playgroud)
如果您的目标是 .NET Core 3.0 或更高版本,则可以使用,它在orBitOperations.PopCount()中运算并返回位数。uintulong1
如果您的 CPU 支持 SSE4,它将使用POPCNTCPU 指令,否则它将使用软件回退。
public static int Count(Skills skillsToCount)
{
return BitOperations.PopCount((ulong)skillsToCount);
}
Run Code Online (Sandbox Code Playgroud)
使用BitArray和LINQ的一种非常简洁的方法:
public static int Count(Skills skillsToCount)
{
return new BitArray(new[] {(int)skillsToCount}).OfType<bool>().Count(x => x);
}
Run Code Online (Sandbox Code Playgroud)