【问题标题】:Test if all higher bits are set测试是否设置了所有高位
【发布时间】:2020-09-12 20:09:07
【问题描述】:

给定一个设置了一个且只有一个位 (n) 的 uint16,我想测试 bit_rank 是否设置了所有更重要的位。我目前正在使用 for 循环,但我敢肯定只有几个运算符有点巧妙。此代码使用编译器,其中位操作生成 32 位 int。

uint16_t b; // loop variable
uint16_t n; // one and only one bit set
uint16_t bit_rank; // contains n and possibly higher/lower bits than n
for (b = n << 1; b < 0x10000; b <<= 1)
    if (b & bit_rank)
        continue;
    else
        break;
if (b == 0x10000)
    printf("all bits from n to 0x8000 are set");

【问题讨论】:

  • 有效吗?最后一个比较(b == 0x10000) 对我来说似乎有点可疑......(双关语不是故意的)
  • 不确定是否完全了解您想要什么,但if (n &amp; bit_rank == n) 不是您需要的吗?
  • 您可以添加具有预期输出的数据样本吗?
  • 这样做不会测试是否设置了位列中比 n 更多的有效位,它只会测试位列中的第 n 位是否设置
  • 如果 b 是 uint16_t 则 b &lt; 0x10000始终为真,b == 0x10000 始终为假

标签: c bit-manipulation


【解决方案1】:

如果无符号值 b 恰好设置了一位,则将 b 添加到相同类型的某个无符号值 x 上,并将结果强制转换为该类型(如果小于“int”)将产生一个至少等于的值到 b,如果 b 或任何更高位被清除,并且如果 b 和所有更高位被设置,则小于 b。

请注意,如果 b 和 x 的类型小于“无符号”,则在“所有高位集”的情况下将 b 添加到 x 将产生太大而无法容纳 b 和 x 的类型的结果。将结果强制转换或强制转换为较小的类型会产生小于 b 的值,否则结果会更大。

【讨论】:

  • 比我的回答好多了。所有 OP 需求是:uint16_t c = bit_rank + n; if (c &lt; n) printf("bit_rank has bit N and all the more significant bits set\n");
  • @4386427 不。如果设置了大于 n 的任何单个位,则被否定。
  • @4386427 以前我写过你的答案是错误的,但现在我意识到你的解决方案使用了溢出并且看起来很正确。谢谢你。很好的答案。
  • @BSalita 似乎这里有点混乱。此答案由 supercat 编写。不是我写的。我确实发布了一个答案,但又删除了它,因为这个答案比我的好。顺便说一句:如果这个答案对您有所帮助,请考虑接受它。
  • @4386427 我认为代码胜过文字。他的回答缺少代码。这就是您在评论中留下代码的原因。我感谢你们,但我更喜欢标记的答案,因为它的代码同样好,但答案更健壮。
【解决方案2】:

另一个简单的解决方案是

((uint16_t) ~bit_rank) < n

这有效,因为对于小于n 的东西,n 的位加上所有更高位需要为零,这意味着bit_rank(假设确实包含n 的位)具有所有比n 设置的位高。

【讨论】:

  • 看起来你的回答和@4386427 留下的评论同样好和聪明。我将您的答案标记为正确。
  • @bsalita:如果这个答案是正确的,那么你就错误地陈述了这个要求。考虑n == 1bit_rank == 0xfffebit_rank 设置了高于n 的所有位,但(uint16_t)~bit_rank 为1,而不是&lt; n。因此,您的需求陈述和问题中的代码可能都不正确,您的意思是“bit_rank 设置了 n 和 所有高阶位。”如果是这样,您应该更正问题(我将删除我的答案,这是针对实际问题中的规范)。
  • 问题中bit_rank 的评论指出“包含 n 并且可能比 n 更高/更低的位”,我将其解释为已知在 n 中设置的位也设置在bit_rank,正如你所建议的那样。
  • @FalkHüffner 没错。必须完整阅读问题才能形成正确的答案。这是 stackoverflow 上的常见问题。
  • @FalkHüffner:但这不是代码实际所做的,因为循环以b = n &lt;&lt; 1 开头。我的阅读基于问题中的文本以及示例代码的行为,它们是一致的。同样可以说,SO 的一个常见问题是措辞不一致的问题。
【解决方案3】:

尝试通过设置 n 中的任何位位置来右移 (>>) 您的位等级。然后你只有比位等级中的那个位置更重要的位。然后反转(~)右移位秩的位,并测试该值,如果为 0,则您知道所有更重要的位都已设置。如果没有,那么并不是所有的都设置好了。

【讨论】:

  • 不。用这个简单的例子反驳:~(0xffffffff >> 1) 是 0x80000000,而不是 0。
【解决方案4】:

我现在无法访问编译器,请原谅编译错误, 但这是我在一般行中使用的解决方案:

第 1 步:准备所需的面具。这是作为静态变量数组完成的,以提高性能(函数不需要在每次调用时在堆栈上分配数组)。

注意:掩码中的每个条目都与您需要的相关 n 掩码相关。以便 mask[3] 表示从 n 到设置的位。

static masks[17] = { 0b0000000000000000, //this entry is not in use
                     0b1111111111111111, //or use 0xFFFF
                     0b1111111111111110  //or use 0xFFFD
                     0b1111111111111100, //or use 0xFFFB
                     0b1111111111111000, //or use 0xFFF8
                     ...
                     }

                 

现在您可以直接访问您想要的号码

if ( ( bit_rank & mask[n] ) == mask(n) )
    printf( "all bits fron n and on, are set\n" );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2018-05-18
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多