使用C中的按位运算符检查数字是否为非零

Ete*_*ner 25 c bit-manipulation

x使用合法运算符检查数字是否为非零值!.

例如:isNonZero(3) = 1,isNonZero(0) = 0

法律行动: ~ & ^ | + << >>

  • 注意:只应使用按位运算符.if,else,for等不能使用.
  • 编辑1:运营商数量不应超过10.
  • Edit2:考虑大小为int4个字节.

int isNonZero(int x) {
return ???;
}
Run Code Online (Sandbox Code Playgroud)

使用!它将是微不足道的,但我们如何不使用!

rus*_*lik 41

adamk函数的对数版本:

int isNotZero(unsigned int n){
  n |= n >> 16;
  n |= n >> 8;
  n |= n >> 4;
  n |= n >> 2;
  n |= n >> 1;
  return n & 1;
};
Run Code Online (Sandbox Code Playgroud)

最快的一个,但是在组装中:

xor eax, eax
sub eax, n  // carry would be set if the number was not 0
xor eax, eax
adc eax, 0  // eax was 0, and if we had carry, it will became 1
Run Code Online (Sandbox Code Playgroud)

类似于汇编版本的东西可以用C编写,你只需要使用符号位和一些差异.

编辑:这是我在C中能想到的最快的版本:

1)对于负数:如果设置了符号位,则该数字不为0.

2)对于积极的:0 - n将是否定的,并且可以按照案例1进行检查.我没有-在合法操作列表中看到,所以我们将使用~n + 1.

我们得到了什么:

int isNotZero(unsigned int n){ // unsigned is safer for bit operations
   return ((n | (~n + 1)) >> 31) & 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 您在这里使用11位运算符.(5x |,5x >>,1x&). (5认同)
  • “ sub”不是按位操作;如果我们允许-1,那么C ++解决方案会更容易 (2认同)
  • 你为什么不用neg?xor eax,eax; neg ecx; adc eax,0; (2认同)

ust*_*sta 11

int isNonZero(unsigned x) {
    return ~( ~x & ( x + ~0 ) ) >> 31;
}
Run Code Online (Sandbox Code Playgroud)

假设int是32位(/*EDIT:这部分不再适用,因为我将参数类型更改为无符号*/并且有符号的移位与无符号移位的行为完全相同).


kri*_*iss 9

为什么让事情复杂化?

int isNonZero(int x) {
    return x;
}
Run Code Online (Sandbox Code Playgroud)

它的工作原理是因为C约定是每个非零值都表示正确,因为isNonZero返回一个合法的int.

有人认为,isNonZero()函数应该为输入3返回1,如示例中所示.

如果您使用的是C++,它仍然像以前一样简单:

int isNonZero(int x) {
    return (bool)x;
}
Run Code Online (Sandbox Code Playgroud)

现在函数返回1,如果你提供3.

好吧,它不适用于C错过适当的布尔类型.

现在,如果你认为int是32位且允许+:

int isNonZero(int x) {
    return ((x|(x+0x7FFFFFFF))>>31)&1;
}
Run Code Online (Sandbox Code Playgroud)

在某些体系结构上,您甚至&1可以通过将x转换为unsigned(具有空运行时成本)来避免最终结果,但这是未定义行为,因此依赖于实现(取决于目标体系结构是使用带符号还是逻辑右移).

int isNonZero(int x) {
    return ((unsigned)(x|(x+0x7FFFFFFF)))>>31;
}
Run Code Online (Sandbox Code Playgroud)

  • 好的,但你的功能也不符合这个例子. (8认同)
  • 因为那不是要求。要求是为非零返回 1 (2认同)