有条件使用位运算符

问题描述 投票:0回答:6

条件运算符如何使用按位运算符表示?

这是一个家庭作业问题,我必须仅使用按位运算来实现条件运算符。如果允许

if
语句,那就很简单,但它必须是严格的按位运算符。

只能使用运算符

!
~
&
^
|
+
>>
<<
》。不能使用
if
语句或循环。

该函数需要三个整数,其工作方式与普通条件运算符类似。第一个参数被评估为零或非零。如果第一个参数为零,则返回第二个参数。如果第一个参数非零,则返回第三个参数。

我希望有一个简单的算法可以解决这个问题。任何关于从哪里开始的想法都会有很大的帮助。

c bit-manipulation
6个回答
11
投票

是否允许使用移位作为按位运算符?允许算术运算符吗?

您的编辑并不完全清楚,但我认为您需要实现等效的

a ? b : c

其中

a
b
c
是整数。这又相当于

a != 0 ? b : c

实现这一目标的一种方法是找到一种仅使用按位运算符将

a
的非零值转换为全 1 位模式的方法。如果我们弄清楚如何做到这一点,那么剩下的事情就很容易了。现在,我并没有立即记得任何可以做到这一点的巧妙技巧(我相信它们确实存在),而且我不确定哪些运算符是允许的,哪些是不允许的,所以现在我只使用类似的东西

a |= a >> 1; a |= a >> 2; a |= a >> 4; a |= a >> 8; a |= a >> 16;
a |= a << 1; a |= a << 2; a |= a << 4; a |= a << 8; a |= a << 16;

对于 32 位整数类型,如果(且仅当)原始

a
中至少设置了一位,则上述操作应导致
a
的所有位都设置为 1。(假设我们正在工作使用无符号整数,以避免与有符号值移位相关的问题)。再说一次,我确信一定有更聪明的方法来做到这一点。例如:
a = !a - 1
,但不知道
!
-
是否允许

一旦我们这样做了,原来的条件运算符就相当于

(a & b) | (~a & c)

完成。


8
投票

基本上不是。条件运算符将仅计算第二个或第三个操作数中的one;位运算符总是计算两个操作数。

我认为从按位运算符开始考虑条件运算符确实没有意义......例如,如果第二个和第三个操作数是指针类型,您就不会想考虑那些 在按位运算方面,你会吗?将条件运算符与按位运算符分开对待 - 尝试合并它们不会给自己带来任何好处。


2
投票

我认为OP正在寻找一种方法来表达通常需要无分支方式条件的事物。例如(假设

unsigned x,y,z;
x
INT_MAX
为界):

if (x>2) y+=z;

可表示为:

y += z & -(2-x >> sizeof(unsigned)*CHAR_BIT-1);

我之所以想到这个例子,是因为我曾多次在“无分支二进制排序”中使用它。当被搜索的数组的大小恒定时,这允许将搜索循环完全展开为一系列没有分支的操作,并且每步仅编译为几个操作码。那些反对编写“C 汇编程序”的人可能更喜欢这样写:

y += (x>2) ? z : 0;

并希望编译器生成等效的位掩码或

cmov
指令。 :-)


0
投票

如果您指的是三元选择运算符,则可以使用按位运算来表示,但仅限于某些情况(实际上,在某些情况下使用按位运算是一种优化)。例如:

(getsomevalue() == 1) ? somepointer : NULL;
可以表示为
somepointer & ~((unsigned)(getsomevalue()) - 1);
假设
getsomevalue()
仅返回 1 或 0(又名 BOOL)


0
投票

这是一篇旧帖子,但当我为我的班级分配类似的作业时,我发现了它。这篇文章中的答案使用了太多的运算符来满足要求(最多 16 个运算符)。然而,在概念上仍然很有帮助。

这是我最终找到的解决方案:

一个?乙:丙

x = a >> 31; //如果为正则为 00...00 如果为负则为 11...11

y = (~a + 1) >> 31; //如果为正,则为 11...11;如果为负,则为 00...00

//如果 a 为零,则 x 和 y 都应该为 0,因为 y def 中的+1

z = x |是;

解决方案 (z 和 b) | (~z & c);

这是利用 C 中的移位是算术而非逻辑这一事实。


-1
投票

在最基本的层面上,它变成了电子产品。请参阅这个。我想不出任何其他应用程序来回答你的问题。

© www.soinside.com 2019 - 2024. All rights reserved.