使用C中的按位运算符检查数字是否为非零
使用合法运算符检查数字x
是否非零!
。
示例: isNonZero(3) = 1
, isNonZero(0) = 0
法律操作: ~
&
^
|
+
<<
>>
- 注意:只应使用按位运算符。
if
,else
,for
等不能使用。 - 编辑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.(〜0在二进制补码机上产生减一。这是一个假设。)
- 只选择翻转为1的翻转位。
- 如果
x
为零,则最有效位仅因减1而翻转。 - 将最高有效位移至最低有效位。
我算六个运营商。 我可以使用0xFFFFFFFF
五。 对unsigned
不依赖于二进制补码机; v)。
基本上你需要或位。 例如,如果您知道您的数字是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);