简体   繁体   English

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

[英]How to Implement the Pattern 2^n-1 using Bitwise Operators

While programming with bitwise operations I had a doubt. 在使用按位运算进行编程时,我有一个疑问。 That is,in my project at one point of time I need to set bits like this, if I type '1' it means the 1st bit is set. 也就是说,在我的项目的某个时间点,我需要设置这样的位,如果我键入“ 1”,则意味着设置了第一个位。 If I type '2' it means the first 2 bits are set. 如果我键入“ 2”,则意味着前2位被设置。

So, 所以,

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

Likewise it goes. 同样的。 From this I analyze the following pattern.That is 1-1,11-3,111-7,1111-15. 由此,我分析了以下模式,即1-1,11-3,111-7,1111-15。

That is 2^1-1=1,2^2-1=3,2^3-1=7,... 那就是2 ^ 1-1 = 1,2 ^ 2-1 = 3,2 ^ 3-1 = 7,...

Now I need to write bitwise operations for this format in a single Line. 现在,我需要在一行中为此格式编写按位运算。

Any help is appreciated. 任何帮助表示赞赏。

So far we've had "the main two answers" that you usually get to this question. 到目前为止,我们已经对这个问题有了“主要的两个答案”。 They're different in their edge conditions. 他们的边缘条件不同。 Assuming 32bit unsigned integers to take something common, the (1u<<n)-1 answer can handle 0 through 31, and the 0xFFFFFFFF>>(32-n) answer can handle 1 through 32. 假设32位无符号整数采用某些通用标准,则(1u<<n)-1答案可以处理0到31,而0xFFFFFFFF>>(32-n)答案可以处理1到32。

A question that often arises then is, can we have 0 through 32? 那么经常出现的一个问题是,我们可以有0到32吗?

And you can, but naturally it is more complicated, especially if you don't accept conditionals. 而且可以,但是自然会更复杂,尤其是如果您不接受条件句。 The full range is easy to make by combining either approach with a ternary operator, but without that, there are still ways. 通过将两种方法与三元运算符结合起来,很容易实现全部范围,但是如果没有这种方法,仍然有很多方法。

Note that n=32 is the only case in which the bit 0b00100000 is set in n . 注意,只有n=32是在n设置位0b00100000的唯一情况。

So one thing we can do is extract that bit, invert it, and shift it left (being careful not to execute an undefined shift), like this: 因此,我们可以做的一件事是提取该位,将其反转,然后向左移动(注意不要执行未定义的移位),如下所示:

((n >> 5 ^ 1) << (n & 31)) - 1

Now if n < 32 , it simplifies to the old (1u << n) - 1 . 现在,如果n < 32 ,则简化为旧的(1u << n) - 1 If n == 32 , it simplifies to (0 << irrelevant) - 1 , where irrelevant happens to be 0 but we could have chosen anything from 0 through 31. 如果n == 32 ,则简化为(0 << irrelevant) - 1 ,其中irrelevant恰好是0,但我们可以选择0到31之间的任何值。

In some languages (notably C# and Java), shifting by the width of an integer or more is defined and the & 31 can be removed. 在某些语言(尤其是C#和Java)中,定义了整数或更大整数的偏移量,并且& 31可以删除。 In some assembly languages, for example PowerPC, shifting by the width of an integer results in 0, in that case the assembly level equivalent of (1u << n) - 1 would work as-is. 在某些汇编语言(例如PowerPC)中,移位整数的宽度将导致0,在这种情况下,等效于(1u << n) - 1的汇编级别将按原样工作。

In other assembly languages there may be other tricks, often using special instructions that have no direct equivalent in high level languages. 在其他汇编语言中,可能还有其他技巧,通常使用特殊的指令,而这些指令在高级语言中没有直接等效的功能。 For example on x86 with BMI1: 例如在带有BMI1的x86上:

or rax, -1
shl ecx, 8
bextr rax, rax, rcx

Or on x86 with BMI2: 或在带有BMI2的x86上:

or rax, -1
bzhi rax, rax, rcx

1 << n gives 2 ^ n , so you may need this one for 2 ^ n - 1 : 1 << n给出2 ^ n ,因此对于2 ^ n - 1可能需要这个:

static inline unsigned int test(int n)
{
    return (1u << n) - 1;
}

With an unsigned int (let's say 32 bits), you can get the value from bitcount as follows: 使用unsigned int(假设为32位),您可以从bitcount中获取值,如下所示:

value = 0xffffffffU >> (32-bitcount);

For example, let's use a bitcount of 3: 例如,让我们使用3的位bitcount

  0xffffffff >> (32-bitcount)
= 0xffffffff >> 29
= 0x00000007

The following program shows this in action: 以下程序显示了这一操作:

#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;
}

The output of that program shows that each subsequent bitcount adds one more 1-bit on the right: 该程序的输出显示,每个后续位计数在右侧又增加了一个1-bit

 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM