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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:40:34  来源:igfitidea点击:

Check if a number is non zero using bitwise operators in C

cbit-manipulation

提问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.
  • 注意:只能使用按位运算符。ifelsefor等不能使用。
  • 编辑 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;
}
  1. Subtract 1. (~0generates minus one on a two's complement machine. This is an assumption.)
  2. Select only flipped bit that flipped to one.
  3. Most significant bit only flips as a result of subtracting one if xis zero.
  4. Move most-significant bit to least-significant bit.
  1. 减去 1。(~0在二进制补码机上生成负1。这是一个假设。)
  2. 仅选择翻转为 1 的翻转位。
  3. 最高有效位仅作为减一的结果翻转,如果x为零。
  4. 将最高有效位移动到最低有效位。

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) 。

http://ideone.com/Omobw

http://ideone.com/Omobw

回答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);
}