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

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

示例: isNonZero(3) = 1isNonZero(0) = 0

法律操作: ~ & ^ | + << >>

  • 注意:只应使用按位运算符。 ifelsefor等不能使用。
  • 编辑1:运营商数量不应超过10。
  • Edit2:将int大小视为4个字节。

 int isNonZero(int x) { return ???; } 

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

adamk函数的对数版本:

 int isNotZero(unsigned int n){ n |= n >> 16; n |= n >> 8; n |= n >> 4; n |= n >> 2; n |= n >> 1; return n & 1; }; 

而最快的一个,但在汇编:

 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 

类似于汇编版本的东西可以用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; } 
 int isNonZero(unsigned x) { return ~( ~x & ( x + ~0 ) ) >> 31; } 

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

为什么让事情复杂化?

 int isNonZero(int x) { return x; } 

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

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

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

 int isNonZero(int x) { return (bool)x; } 

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

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

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

 int isNonZero(int x) { return ((x|(x+0x7FFFFFFF))>>31)&1; } 

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

 int isNonZero(int x) { return ((unsigned)(x|(x+0x7FFFFFFF)))>>31; } 

按位OR或数字中的所有位:

 int isByteNonZero(int x) { return ((x >> 7) & 1) | ((x >> 6) & 1) | ((x >> 5) & 1) | ((x >> 4) & 1) | ((x >> 3) & 1) | ((x >> 2) & 1) | ((x >> 1) & 1) | ((x >> 0) & 1); } int isNonZero(int x) { return isByteNonZero( x >> 24 & 0xff ) | isByteNonZero( x >> 16 & 0xff ) | isByteNonZero( x >> 8 & 0xff ) | isByteNonZero( x & 0xff ); } 
 int is_32bit_zero( int x ) { return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31; } 
  1. 减去1.(〜0在二进制补码机上产生减一。这是一个假设。)
  2. 只选择翻转为1的翻转位。
  3. 如果x为零,则最有效位仅因减1而翻转。
  4. 将最高有效位移至最低有效位。

我算六个运营商。 我可以使用0xFFFFFFFF五。 对unsigned不依赖于二进制补码机; v)。

http://ideone.com/Omobw

基本上你需要或位。 例如,如果您知道您的数字是8位宽:

 int isNonZero(uint8_t x) { int res = 0; res |= (x >> 0) & 1; res |= (x >> 1) & 1; res |= (x >> 2) & 1; res |= (x >> 3) & 1; res |= (x >> 4) & 1; res |= (x >> 5) & 1; res |= (x >> 6) & 1; res |= (x >> 7) & 1; return res; } 

我的解决方案如下,

 int isNonZero(int n) { return ~(n == 0) + 2; } 

我的解决方案是C.没有比较运算符。 不适用于0x80000000。

 #include  int is_non_zero(int n) { n &= 0x7FFFFFFF; n *= 1; return n; } int main(void) { printf("%d\n", is_non_zero(0)); printf("%d\n", is_non_zero(1)); printf("%d\n", is_non_zero(-1)); return 0; } 

我的解决方案虽然与您的问题不太相关

int isSign(int x)

 { //return 1 if positive,0 if zero,-1 if negative return (x > 0) - ((x & 0x80000000)==0x80000000) } 

以下函数示例应该适合您。

 bool isNonZero(int x) { return (x | 0); } 

如果非零,此函数将返回x ,否则返回0

 int isNonZero(int x) { return (x); } 
 if(x) printf("non zero") else printf("zero") 

int isNonZero(int x)

{

 if ( x & 0xffffffff) return 1; else return 0; 

}

假设Int是4个字节。

如果值不为零,它将返回1

如果value为零则返回0。

return((val&0xFFFFFFFF)== 0?0:1);