C语言 使用 C 中的按位运算符检查数字是否为非零
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3912112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if a number is non zero using bitwise operators in C
提问by Eternal Learner
Check whether a number xis nonzero using the legal operators except !.
x使用合法运算符检查数字是否为非零,除了!.
Examples: isNonZero(3) = 1, isNonZero(0) = 0
例子:isNonZero(3) = 1,isNonZero(0) = 0
Legal ops: ~&^|+<<>>
法律行动: ~&^|+<<>>
- Note : Only bitwise operators should be used.
if,else,for, etc. cannot be used. - Edit1 : No. of operators should not exceed 10.
- Edit2 : Consider size of
intto be 4 bytes.
- 注意:只能使用按位运算符。
if、else、for等不能使用。 - 编辑 1:操作员的数量不应超过 10。
- Edit2:考虑大小为
int4 个字节。
int isNonZero(int x) {
return ???;
}
Using !this would be trivial , but how do we do it without using !?
使用!this 是微不足道的,但是我们如何在不使用的情况下做到这一点!?
回答by ruslik
The logarithmic version of the adamk function:
adamk 函数的对数版本:
int isNotZero(unsigned int n){
n |= n >> 16;
n |= n >> 8;
n |= n >> 4;
n |= n >> 2;
n |= n >> 1;
return n & 1;
};
And the fastest one, but in assembly:
最快的,但在组装中:
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
Something similar to assembly version can be written in C, you just have to play with the sign bit and with some differences.
类似于汇编版本的东西可以用 C 编写,你只需要处理符号位和一些差异。
EDIT: here is the fastest version I can think of in C:
编辑:这是我能想到的最快的 C 版本:
1) for negative numbers: if the sign bit is set, the number is not 0.
1) 对于负数:如果设置了符号位,则数字不为 0。
2) for positive: 0 - nwill be negaive, and can be checked as in case 1. I don't see the -in the list of the legal operations, so we'll use ~n + 1instead.
2) for positive:0 - n将是否定的,可以像情况1一样检查。我-在合法操作列表中没有看到,所以我们将使用它~n + 1。
What we get:
我们得到的:
int isNotZero(unsigned int n){ // unsigned is safer for bit operations
return ((n | (~n + 1)) >> 31) & 1;
}
回答by usta
int isNonZero(unsigned x) {
return ~( ~x & ( x + ~0 ) ) >> 31;
}
Assuming int is 32 bits (/* EDIT: this part no longer applies as I changed the parameter type to unsigned */ and that signed shifts behave exactly like unsigned ones).
假设 int 是 32 位(/* 编辑:这部分不再适用,因为我将参数类型更改为无符号 */ 并且有符号移位的行为与无符号移位完全一样)。
回答by kriss
Why make things complicated ?
为什么要把事情复杂化?
int isNonZero(int x) {
return x;
}
It works because the C convention is that every non zero value means true, as isNonZero return an int that's legal.
它有效是因为 C 约定是每个非零值都表示为真,因为 isNonZero 返回一个合法的 int。
Some people argued, the isNonZero() function should return 1 for input 3 as showed in the example.
有些人认为, isNonZero() 函数应该为输入 3 返回 1,如示例所示。
If you are using C++ it's still as easy as before:
如果您使用 C++,它仍然像以前一样简单:
int isNonZero(int x) {
return (bool)x;
}
Now the function return 1 if you provide 3.
现在,如果您提供 3,该函数将返回 1。
OK, it does not work with C that miss a proper boolean type.
好的,它不适用于缺少正确布尔类型的 C。
Now, if you suppose ints are 32 bits and + is allowed:
现在,如果你假设整数是 32 位并且 + 是允许的:
int isNonZero(int x) {
return ((x|(x+0x7FFFFFFF))>>31)&1;
}
On some architectures you may even avoid the final &1, just by casting x to unsigned (which has a null runtime cost), but that is Undefined Behavior, hence implementation dependant (depends if the target architecture uses signed or logical shift right).
在某些体系结构上,您甚至可以避免使用 final &1,只需将 x 强制转换为 unsigned (其运行时成本为空),但这是未定义行为,因此依赖于实现(取决于目标体系结构是否使用有符号或逻辑右移)。
int isNonZero(int x) {
return ((unsigned)(x|(x+0x7FFFFFFF)))>>31;
}
回答by Potatoswatter
int is_32bit_zero( int x ) {
return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31;
}
- Subtract 1. (
~0generates minus one on a two's complement machine. This is an assumption.) - Select only flipped bit that flipped to one.
- Most significant bit only flips as a result of subtracting one if
xis zero. - Move most-significant bit to least-significant bit.
- 减去 1。(
~0在二进制补码机上生成负1。这是一个假设。) - 仅选择翻转为 1 的翻转位。
- 最高有效位仅作为减一的结果翻转,如果
x为零。 - 将最高有效位移动到最低有效位。
I count six operators. I could use 0xFFFFFFFFfor five. The cast to unsigneddoesn't count on a two's complement machine ;v) .
我数了六个操作员。我可以用0xFFFFFFFF五个。演员表unsigned不依赖于二进制补码机 ;v) 。
回答by adamk
Bitwise OR all bits in the number:
按位或数字中的所有位:
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 );
}
回答by Nathan Fellman
basically you need to or the bits. For instance, if you know your number is 8 bits wide:
基本上你需要或位。例如,如果您知道您的数字是 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;
}
回答by TayyaR
My solution is the following,
我的解决方案如下,
int isNonZero(int n)
{
return ~(n == 0) + 2;
}
回答by wannik
My solution in C. No comparison operator. Doesn't work with 0x80000000.
我在 C 中的解决方案。没有比较运算符。不适用于 0x80000000。
#include <stdio.h>
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;
}
回答by Tracy
My solution,though not quite related to your question
我的解决方案,虽然与你的问题不太相关
int isSign(int x)
int isSign(int x)
{
//return 1 if positive,0 if zero,-1 if negative
return (x > 0) - ((x & 0x80000000)==0x80000000)
}
回答by aaj
This function will return xif it is non-zero, otherwise it will return 0.
x如果它不为零,则此函数将返回,否则将返回0。
int isNonZero(int x)
{
return (x);
}

