提取设置为 HashSet 的位

本文关键字:uint 的位 HashSet 设置 提取 | 更新日期: 2023-09-27 18:32:44

c# 中是否有一种方便的方法(使用 linq 或类似方法)将 uint 的真实位提取到HashSet<uint>中?

例:

  private HashSet<uint> ExtractTrueBitsFromSum(uint sum)
  {
  } 
calling it with 15 returns the set `{1,2,4,8}`
calling it with 23 returns the set `{1,2,4,16}`
calling it with 31 returns the set `{1,2,4,8,16}`

提取设置为 HashSet<uint> 的位

private HashSet<uint> ExtractTrueBitsFromSum(uint sum) {
    HashSet<uint> result = new HashSet<uint>();
    while(sum>0) {
        uint newSum = sum&(sum-1); // newSum = sum with least significant True bit set to False.
        result.Add(sum^newSum);    // sum^newSum return least significant True bit of sum.
        sum=newSum;
    }
    return result;
}

我只会使用明显的循环,而不打扰 Linq:

private HashSet<uint> ExtractTrueBitsFromSum(uint sum)
{
    var set = new HashSet<uint>();
    for (uint j = 1; j != 0; j <<= 1)
        if ((sum & j) != 0)
            set.Add(j);
    return set;
}
我认为这不是

使用LINQ的任何理由。

private static HashSet<uint> ExtractTrueBitsFromSum(uint sum)
{
    var result = new HashSet<uint>();
    for (int i = 0; i < 32; i++)
    {
        if (((sum >> i) & 0x1) == 1)
            result.Add((uint)((1 << i)));
    }
    return result;
}

似乎适用于int s:

int n = 23;
string str = Convert.ToString(n, 2);

HashSet<int> result = new HashSet<int>(str.Select((c, index) => 
                             int.Parse(c.ToString()) > 0 ? (int)Math.Pow(2, index) : 0));
result.Remove(0);

编辑 - 以考虑位的颠倒顺序:

HashSet<int> result = new HashSet<int>(str.Reverse().Select((c, index) => 
                             int.Parse(c.ToString()) > 0 ? (int)Math.Pow(2, index) : 0));
result.Remove(0);

编辑 2:

HashSet<uint> result = new HashSet<uint>(str.Reverse().Select((c, index) => 
                              int.Parse(c.ToString()) > 0 ? (uint)Math.Pow(2, index) : 0));
result.Remove(0);

如果您更喜欢 LINQ:

private HashSet<uint> ExtractTrueBitsFromSum(uint sum)
{
    var bits = Convert.ToString(sum, toBase: 2);
    return new HashSet<uint>(
                bits.Select((bit, index) => (uint)(bit - '0') << (bits.Length - index - 1))
                    .Where(pow => pow > 0));
}