使用位运算符,找到一个逻辑不等价

Posted

技术标签:

【中文标题】使用位运算符,找到一个逻辑不等价【英文标题】:Using bitwise operators, find a logical not equivalent 【发布时间】:2011-11-09 22:25:47 【问题描述】:

仅使用

<< >> | ^ & +

如何创建一个等效于逻辑非运算符 (!) 的函数?

现在我有:

int i = (~x + 1) >> 31; 
int j = (x + 1) >> 31; 
i = i | j; 
i = i & 1; 
return i ^ 1;

它适用于一切,但-1

【问题讨论】:

您的解决方案使用 ~。我们是否允许使用它?另外,x 是整数还是布尔值? 您的问题指出仅使用这些运算符“> | ^ & +”,但随后您尝试使用“~”? 【参考方案1】:

我假设您使用的是 32 位、有符号并使用 2 的补码表示法的 ints。数字 0 的独特之处在于,无论是 0 还是它的否定符号位都没有 1。如果允许您使用否定运算符 (-),则此代码将起作用:

int not(int x)

    return (-x | x) >> 31 & 1 ^ 1;

您不能使用减号,但这没关系,因为对于所有 x,我们都知道 -x 等于 ~x + 1 等于 (x ^ -1) + 1。这就是 2 的补码符号的工作原理。所以最终的答案是:

int not(int x)

    return ( (x^-1)+1 | x ) >> 31 & 1 ^ 1;

编辑 1: 好的,这是函数的“ANSI”版本,它不假设 int 的大小,也不依赖于右移有符号 int 的未定义行为。它在 MinGW 中对我有用:

int not(int x)

    unsigned int y = x;
    return (( ((y^-1)+1) | y ) >> (sizeof(x)*8-1)) ^ 1;

【讨论】:

不推荐有符号整数右移(实现根据C标准定义)。 是的,抱歉,我的功能因此而失败。我现在将对其进行编辑以添加一个“& 1”以在右移后修剪除 LSB 之外的所有内容。 如果您无法理解我的代码,请阅读:difranco.net/cop2220/op-prec.htm 根据 C 标准(至少是 C89,我稍后会检查 C99),“每个实现都应记录其在本节列出的每个领域中的行为。”所以我真的不能说结果会是什么。 您使用的运算符比问题允许的要多得多(乘法、减法、sizeof)。但我不确定是否有可能解决提出的问题(即至少没有关于整数表示等的一些假设)【参考方案2】:

假设 x 是一个 32 位无符号值:

x = x | (x >> 1)
x = x | (x >> 2)
x = x | (x >> 4)
x = x | (x >> 8)
x = x | (x >> 16)

此时,如果 x 为 0,那么它仍然为 0。如果它有一个非零值,它现在具有位模式 111....111。

使用二补码表示,您现在可以简单地加 1 并获得所需的结果:

x = x + 1

这个解决方案对整数表示、类型等做了很多假设。

(当然,上面的“代码”不是有效的 C 代码)。

【讨论】:

@quasiverse - 然后执行unsigned x = *(unsigned *)&amp;arg;,使用x for your computation, then do arg = (desired_type)x;` 对于有符号整数,右移具有依赖于实现的行为。 Omri,您错误地断言 x 在代码运行后将具有位模式 111111...111111。右移运算符不循环操作。考虑 x 是否为 1。第一个代码块中的任何操作都不会将其更改为 1 以外的值。 @David 当然你是对的。那会教我不要在凌晨 2 点 30 分回答问题... @David 只是一个想法——如果我只接受 LSB 作为答案,它仍然可以工作。但它表明当你累了时编程是多么不明智。【参考方案3】:

有点“作弊”,但是:

bool logicalNot(int i)

    return((bool)i ^ true);

我假设在关于函数组合/类型转换/隐式类型转换的规则中没有任何内容?

【讨论】:

C语言没有bool类型;你能得到的最好的是typedef unsigned char bool,它不能用于这个目的。

以上是关于使用位运算符,找到一个逻辑不等价的主要内容,如果未能解决你的问题,请参考以下文章

奇怪的 if 语句

&、|、^ 是按位运算符还是逻辑运算符?

当按位运算符做同样的事情时,为啥要使用逻辑运算符?

VB运算符在运算式的顺序是啥?

Java运算符使用总结(重点:自增自减位运算和逻辑运算)

为啥按位运算符不如逻辑“和\或”运算符聪明