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

发布于 2024-09-27 16:46:05 字数 581 浏览 1 评论 0原文

使用除 ! 之外的合法运算符检查数字 x 是否非零。

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

合法操作:~ & < code>^ | + << >>

  • 注意:仅限位运算符应该使用。不能使用ifelsefor等。
  • Edit1:运算符数量不应超过 10。
  • Edit2:将 int 的大小视为 4 个字节。

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

使用 ! 这将是微不足道的,但是我们如何在不使用 ! 的情况下做到这一点呢?

Check whether a number x is nonzero using the legal operators except !.

Examples: 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 int to be 4 bytes.
int isNonZero(int x) {
return ???;
}

Using ! this would be trivial , but how do we do it without using ! ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

放飞的风筝 2024-10-04 16:46:06
if(x)
     printf("non zero")
else
     printf("zero")
if(x)
     printf("non zero")
else
     printf("zero")
柠檬心 2024-10-04 16:46:06

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

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

The following function example should work for you.

bool isNonZero(int x)
{
    return (x | 0);
}
甜扑 2024-10-04 16:46:06

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

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

This function will return x if it is non-zero, otherwise it will return 0.

int isNonZero(int x)
{
    return (x);
}
江湖彼岸 2024-10-04 16:46:06

int isNonZero(int x)

{

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

}

假设 Int 是 4 个字节。

如果值非零,则返回 1;

如果值为零,则返回 0。

int isNonZero(int x)

{

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

}

Let assume Int is 4 byte.

It will return 1 if value is non zero

if value is zero then it will return 0.

七分※倦醒 2024-10-04 16:46:06

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

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

唐婉 2024-10-04 16:46:05

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;
}

The logarithmic version of the adamk function:

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.

EDIT: here is the fastest version I can think of in C:

1) for negative numbers: if the sign bit is set, the number is not 0.

2) for positive: 0 - n will 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 + 1 instead.

What we get:

int isNotZero(unsigned int n){ // unsigned is safer for bit operations
   return ((n | (~n + 1)) >> 31) & 1;
}
败给现实 2024-10-04 16:46:05
int isNonZero(unsigned x) {
    return ~( ~x & ( x + ~0 ) ) >> 31;
}

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

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

浮世清欢 2024-10-04 16:46:05

为什么要把事情搞复杂呢?

int isNonZero(int x) {
    return x;
}

它之所以有效,是因为 C 约定是每个非零值都表示 true,因为 isNonZero 返回合法的 int。

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

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

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

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

好吧,它不适用于缺少正确布尔类型的 C。

现在,如果您假设整数是 32 位并且允许 +:

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

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

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

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.

Some people argued, the isNonZero() function should return 1 for input 3 as showed in the example.

If you are using C++ it's still as easy as before:

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

Now the function return 1 if you provide 3.

OK, it does not work with C that miss a proper boolean type.

Now, if you suppose ints are 32 bits and + is allowed:

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

int isNonZero(int x) {
    return ((unsigned)(x|(x+0x7FFFFFFF)))>>31;
}
极致的悲 2024-10-04 16:46:05
int is_32bit_zero( int x ) {
    return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31;
}
  1. 减 1。(~0 在补码机上生成减一。这是一个假设。)
  2. 仅选择翻转为 1 的翻转位。
  3. 如果x 为零,则最高有效位仅因减一而翻转。
  4. 将最高有效位移至最低有效位。

我数了一下,有六个操作员。我可以使用 0xFFFFFFFF 来表示五个。转换为 unsigned 不依赖于二进制补码机器 ;v) 。

http://ideone.com/Omobw

int is_32bit_zero( int x ) {
    return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31;
}
  1. Subtract 1. (~0 generates 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 x is zero.
  4. Move most-significant bit to least-significant bit.

I count six operators. I could use 0xFFFFFFFF for five. The cast to unsigned doesn't count on a two's complement machine ;v) .

http://ideone.com/Omobw

后来的我们 2024-10-04 16:46:05

按位或数字中的所有位:

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

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 );
}
So要识趣 2024-10-04 16:46:05

基本上你需要或位。例如,如果您知道您的号码是 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;
}

basically you need to or the bits. For instance, if you know your number is 8 bits wide:

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;
}
孤城病女 2024-10-04 16:46:05

我的解决方案如下,

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

My solution is the following,

int isNonZero(int n)
{
    return ~(n == 0) + 2;
}
谁把谁当真 2024-10-04 16:46:05

我的 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;
}

My solution in C. No comparison operator. Doesn't work with 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;
}
清眉祭 2024-10-04 16:46:05

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

int isSign(int x)

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

My solution,though not quite related to your question

int isSign(int x)

{
//return 1 if positive,0 if zero,-1 if negative
return (x > 0) - ((x & 0x80000000)==0x80000000)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文