首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用位运算符实现模式2^n-1

如何使用位运算符实现模式2^n-1
EN

Stack Overflow用户
提问于 2014-08-28 14:10:36
回答 3查看 1.2K关注 0票数 2

在使用按位操作进行编程时,我有一个疑问。也就是说,在我的项目中,在某个时间点,我需要像这样设置位,如果我输入'1‘,它意味着第一位被设置。如果我输入'2‘,它意味着前2位已设置。

所以,

1-1 2-11 3-111 4-1111

同样,它也是如此。

现在,我需要在一行中编写这种格式的逐位操作。

任何帮助都是非常感谢的。

EN

回答 3

Stack Overflow用户

发布于 2014-08-28 18:53:34

到目前为止,我们已经有了“两个主要的答案”,你通常会得到这个问题。它们的边缘条件是不同的。假设32位无符号整数取公共值,(1u<<n)-1答案可以处理0到31,0xFFFFFFFF>>(32-n)答案可以处理1到32。

然后经常会出现的一个问题是,我们可以从0到32吗?

你可以,但很自然地,它会更复杂,特别是如果你不接受条件句的话。通过将这两种方法中的任何一种与三元运算符相结合,很容易实现完整的范围,但如果不这样做,仍然有方法可用。

请注意,n=32是在n中设置位0b00100000的唯一情况。

因此,我们可以做的一件事是提取该位,反转它,并将其向左移位(注意不要执行未定义的移位),如下所示:

代码语言:javascript
运行
复制
((n >> 5 ^ 1) << (n & 31)) - 1

现在如果是n < 32,它将简化为旧的(1u << n) - 1。如果为n == 32,则简化为(0 << irrelevant) - 1,其中irrelevant恰好为0,但我们可以选择0到31之间的任何值。

在一些语言(特别是C#和Java)中,定义了按整数或更大整数的宽度进行移位,并且可以删除& 31。在某些汇编语言中,例如PowerPC,将整数的宽度移位会导致0,在这种情况下,(1u << n) - 1的汇编级等效项将按原样工作。

在其他汇编语言中可能还有其他技巧,通常使用高级语言中没有直接等效的特殊指令。例如,在使用BMI1的x86上:

代码语言:javascript
运行
复制
or rax, -1
shl ecx, 8
bextr rax, rax, rcx

或者在带有BMI2的x86上:

代码语言:javascript
运行
复制
or rax, -1
bzhi rax, rax, rcx
票数 3
EN

Stack Overflow用户

发布于 2014-08-28 14:15:09

1 << n提供了2 ^ n,因此您可能需要在2 ^ n - 1中使用以下代码

代码语言:javascript
运行
复制
static inline unsigned int test(int n)
{
    return (1u << n) - 1;
}
票数 1
EN

Stack Overflow用户

发布于 2014-08-28 14:16:07

使用无符号整型(假设是32位),您可以从bitcount中获得值,如下所示:

代码语言:javascript
运行
复制
value = 0xffffffffU >> (32-bitcount);

例如,让我们使用bitcount 3:

代码语言:javascript
运行
复制
  0xffffffff >> (32-bitcount)
= 0xffffffff >> 29
= 0x00000007

下面的程序实际演示了这一点:

代码语言:javascript
运行
复制
#include <stdio.h>

int cvt (int bc) {
    return 0xffffffffU >> (32-bc);
}

int main (void) {
    for (int bc = 1; bc <= 32; bc++)
        printf ("%2d: 0x%08x %u\n", bc, cvt (bc), cvt (bc));
    return 0;
}

该程序的输出显示,每个后续的位数都会在右侧增加一个1-bit

代码语言:javascript
运行
复制
 1: 0x00000001 1
 2: 0x00000003 3
 3: 0x00000007 7
 4: 0x0000000f 15
 5: 0x0000001f 31
 6: 0x0000003f 63
 7: 0x0000007f 127
 8: 0x000000ff 255
 9: 0x000001ff 511
10: 0x000003ff 1023
11: 0x000007ff 2047
12: 0x00000fff 4095
13: 0x00001fff 8191
14: 0x00003fff 16383
:
30: 0x3fffffff 1073741823
31: 0x7fffffff 2147483647
32: 0xffffffff 4294967295
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25541858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档