Binary 在第一个';1';

Binary 在第一个';1';,binary,integer,bit-manipulation,Binary,Integer,Bit Manipulation,假设是一个32位无符号整数(可以推广到任何大小的答案当然更好) 这个整数可以假定为2的幂,因此只设置了一位。 我想设置整数中的所有位,除了低于设置位的位。因此(为了简洁起见,使用8位整数)00001000将变成11111000 当然,这可以通过找到一个设置的位,然后迭代更高的位来完成,也可以设置它们。假设最高设置返回最高设置位的位置: uint32\u t f(uint32\u t x) { int n=最高_集(x); 对于(int i=31;i!=n;--i){ 从概念上讲,一件简单的事情是

假设是一个32位无符号整数(可以推广到任何大小的答案当然更好)

这个整数可以假定为2的幂,因此只设置了一位。 我想设置整数中的所有位,除了低于设置位的位。因此(为了简洁起见,使用8位整数)
00001000
将变成
11111000

当然,这可以通过找到一个设置的位,然后迭代更高的位来完成,也可以设置它们。假设
最高设置
返回最高设置位的位置:

uint32\u t f(uint32\u t x)
{
int n=最高_集(x);
对于(int i=31;i!=n;--i){

从概念上讲,一件简单的事情是取
x-1
,然后用
0xffffffff
进行异或运算。如哈罗德在下面的评论中所做的那样,将其写成
~(x-1)
将处理不同大小的整数,而无需更改异或运算的内容。

uint32\u t f(uint32\u t x)
{
bool bitset=false;//C++
对于(int i=0;ishift right log(值),
或者使用1的位掩码,
左移日志(值)。

这应该是一个通用的解决方案,对于任何输入都有相同的运行时间,但不能保证。

您只需要取二者的补充

x = -x;
无论x是有符号的还是无符号的,它都可以工作

为什么?因为你所做的基本上是一种将数字转换为2的补码的快速方法

x = -x;
手动将二进制数转换为其2的补码的快捷方式是从最低有效位(LSB)开始,复制所有零(从LSB向最高有效位移动),直到达到第一个1;然后复制该1,并翻转所有剩余位

您只有一个位集,因此当您复制所有零位并反转剩余的零位时,将得到其2的补码。您可以在示例中看到:
000011000=811111000=-8
。其他一些示例:

00010000 = 16, 11110000 = -16
00100000 = 32, 11100000 = -32
01000000 = 64, 11000000 = -64

如果x是有符号类型,那么很容易理解。如果是无符号类型,那么显然没有负值,因此它基于

涉及无符号操作数的计算永远不会溢出,因为不能由结果无符号整数类型表示的结果将被减少为比结果类型可以表示的最大值大一的数的模

也就是说,因为一个大于结果类型(即本例中的
UINTN_MAX+1
)所能表示的最大值的值是2N。即使有符号类型是符号大小或一的补码,对一个无符号值求反也会在C中产生其二的补码

当然,如果您想键入更多,也可以将其强制转换为有符号类型
x=-(int32_t)x;
。您还有另一种解决方案

x = ~x + 1; // by 2's complement definition

易于理解的解决方案

while(!(x&0x8000000))

x |=x您提到的
~(x-1)
解决方案在任何现代产品上都可能更快。代码也更少。@harold同意。我刚刚删除了关于查找表的部分,因为在大多数情况下它感觉更混乱,没有真正的优势。